query leer dict create python json

leer - python json to dict



Mostrar un mensaje de error mejor que "No se pudo decodificar ningĂșn objeto JSON" (9)

Descubrí que el módulo simplejson proporciona más errores descriptivos en muchos casos en los que el módulo json incorporado es impreciso. Por ejemplo, para el caso de tener una coma después del último elemento en una lista:

json.loads(''[1,2,]'') .... ValueError: No JSON object could be decoded

que no es muy descriptivo La misma operación con simplejson :

simplejson.loads(''[1,2,]'') ... simplejson.decoder.JSONDecodeError: Expecting object: line 1 column 5 (char 5)

¡Mucho mejor! Del mismo modo para otros errores comunes como capitalizar True .

Código de Python para cargar datos de un archivo JSON largo y complicado:

with open(filename, "r") as f: data = json.loads(f.read())

(nota: la mejor versión de código debe ser:

with open(filename, "r") as f: data = json.load(f)

pero ambos exhiben un comportamiento similar)

Para muchos tipos de errores JSON (delimitadores faltantes, barras diagonales inversas incorrectas en cadenas, etc.), esto imprime un bonito mensaje útil que contiene la línea y el número de columna donde se encontró el error JSON.

Sin embargo, para otros tipos de errores JSON (incluido el clásico "usar la coma en el último elemento de una lista", pero también otras cosas como mayúsculas / falsas), la salida de Python es justa:

Traceback (most recent call last): File "myfile.py", line 8, in myfunction config = json.loads(f.read()) File "c:/python27/lib/json/__init__.py", line 326, in loads return _default_decoder.decode(s) File "c:/python27/lib/json/decoder.py", line 360, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "c:/python27/lib/json/decoder.py", line 378, in raw_decode raise ValueError("No JSON object could be decoded") ValueError: No JSON object could be decoded

Para ese tipo de ValueError, ¿cómo logra que Python le diga dónde está el error en el archivo JSON?


La respuesta aceptada es la más fácil de solucionar el problema. Pero en caso de que no se le permita instalar el archivo simple debido a la política de su empresa, propongo a continuación la solución para solucionar el problema específico de "usar una coma en el último elemento de una lista" :

  1. Cree una clase secundaria "JSONLintCheck" para heredar de la clase "JSONDecoder" y anule el método init de la clase "JSONDecoder" como se muestra a continuación:

    def __init__(self, encoding=None, object_hook=None, parse_float=None,parse_int=None, parse_constant=None, strict=True,object_pairs_hook=None) super(JSONLintCheck,self).__init__(encoding=None, object_hook=None, parse_float=None,parse_int=None, parse_constant=None, strict=True,object_pairs_hook=None) self.scan_once = make_scanner(self)

  1. make_scanner es una nueva función que reemplazó el método ''scan_once'' de la clase anterior. Y aquí hay un código para esto:

1 #!/usr/bin/env python 2 from json import JSONDecoder 3 from json import decoder 4 import re 5 6 NUMBER_RE = re.compile( 7 r''(-?(?:0|[1-9]/d*))(/./d+)?([eE][-+]?/d+)?'', 8 (re.VERBOSE | re.MULTILINE | re.DOTALL)) 9 10 def py_make_scanner(context): 11 parse_object = context.parse_object 12 parse_array = context.parse_array 13 parse_string = context.parse_string 14 match_number = NUMBER_RE.match 15 encoding = context.encoding 16 strict = context.strict 17 parse_float = context.parse_float 18 parse_int = context.parse_int 19 parse_constant = context.parse_constant 20 object_hook = context.object_hook 21 object_pairs_hook = context.object_pairs_hook 22 23 def _scan_once(string, idx): 24 try: 25 nextchar = string[idx] 26 except IndexError: 27 raise ValueError(decoder.errmsg("Could not get the next character",string,idx)) 28 #raise StopIteration 29 30 if nextchar == ''"'': 31 return parse_string(string, idx + 1, encoding, strict) 32 elif nextchar == ''{'': 33 return parse_object((string, idx + 1), encoding, strict, 34 _scan_once, object_hook, object_pairs_hook) 35 elif nextchar == ''['': 36 return parse_array((string, idx + 1), _scan_once) 37 elif nextchar == ''n'' and string[idx:idx + 4] == ''null'': 38 return None, idx + 4 39 elif nextchar == ''t'' and string[idx:idx + 4] == ''true'': 40 return True, idx + 4 41 elif nextchar == ''f'' and string[idx:idx + 5] == ''false'': 42 return False, idx + 5 43 44 m = match_number(string, idx) 45 if m is not None: 46 integer, frac, exp = m.groups() 47 if frac or exp: 48 res = parse_float(integer + (frac or '''') + (exp or '''')) 49 else: 50 res = parse_int(integer) 51 return res, m.end() 52 elif nextchar == ''N'' and string[idx:idx + 3] == ''NaN'': 53 return parse_constant(''NaN''), idx + 3 54 elif nextchar == ''I'' and string[idx:idx + 8] == ''Infinity'': 55 return parse_constant(''Infinity''), idx + 8 56 elif nextchar == ''-'' and string[idx:idx + 9] == ''-Infinity'': 57 return parse_constant(''-Infinity''), idx + 9 58 else: 59 #raise StopIteration # Here is where needs modification 60 raise ValueError(decoder.errmsg("Expecting propert name enclosed in double quotes",string,idx)) 61 return _scan_once 62 63 make_scanner = py_make_scanner

  1. Mejor ponga la función ''make_scanner'' junto con la nueva clase hija en un mismo archivo.

No podrás conseguir que python te diga dónde está el JSON incorrecto. Tendrá que usar un linter en línea en algún lugar como this

Esto le mostrará un error en el JSON que intenta decodificar.


Para mi versión particular de este problema, seguí y busqué la declaración de función de load_json_file(path) dentro del archivo packaging.py , y luego introduje de contrabando una línea de print en ella:

def load_json_file(path): data = open(path, ''r'').read() print data try: return Bunch(json.loads(data)) except ValueError, e: raise MalformedJsonFileError(''%s when reading "%s"'' % (str(e), path))

De esa forma imprimiría el contenido del archivo json antes de ingresar al try-catch, y de esa manera, incluso con mi conocimiento Python apenas existente, pude averiguar rápidamente por qué mi configuración no podía leer el archivo json.
(Fue porque había configurado mi editor de texto para escribir un BOM UTF-8 ... estúpido)

Solo menciono esto porque, aunque quizás no sea una buena respuesta al problema específico del OP, este fue un método bastante rápido para determinar la fuente de un error muy opresivo. Y apuesto a que muchas personas tropezarán con este artículo que buscan una solución más detallada para un MalformedJsonFileError: No JSON object could be decoded when reading … Entonces eso podría ayudarlos.


Podría usar cjson , que dice ser hasta 250 veces más rápido que las implementaciones de python puro, dado que tiene "algún archivo JSON largo y complicado" y es probable que necesite ejecutarlo varias veces (los decodificadores fallan e informan el primer error que encuentro solamente).


Puede probar la biblioteca de rson que se encuentra aquí: http://code.google.com/p/rson/ . También estoy en PYPI: https://pypi.python.org/pypi/rson/0.9 para que pueda usar easy_install o pip para obtenerlo.

para el ejemplo dado por tom:

>>> rson.loads(''[1,2,]'') ... rson.base.tokenizer.RSONDecodeError: Unexpected trailing comma: line 1, column 6, text '']''

RSON está diseñado para ser un superconjunto de JSON, por lo que puede analizar archivos JSON. También tiene una sintaxis alternativa que es mucho más agradable para que los humanos la puedan ver y editar. Lo uso bastante para los archivos de entrada.

En cuanto a la capitalización de los valores booleanos: parece que rson lee los booleanos con letras mayúsculas incorrectamente como cadenas.

>>> rson.loads(''[true,False]'') [True, u''False'']


Significa que su JSON no es válido, puede usar https://jsonlint.com/ para validar su JSON y encontrar errores en él.


Tuve un problema similar y se debió a las comillas simples. El estándar JSON ( http://json.org ) solo habla sobre el uso de comillas dobles, por lo que la biblioteca python json solo admite comillas dobles.


Tuve un problema similar, este era mi código:

json_file=json.dumps(pyJson) file = open("list.json",''w'') file.write(json_file) json_file = open("list.json","r") json_decoded = json.load(json_file) print json_decoded

el problema era que había olvidado file.close() Lo hice y solucioné el problema.