Code Python pour charger des données depuis un fichier JSON long et compliqué:
with open(filename, "r") as f:
data = json.loads(f.read())
(note: la meilleure version du code devrait être:
with open(filename, "r") as f:
data = json.load(f)
mais les deux présentent un comportement similaire)
Pour de nombreux types d'erreur JSON (délimiteurs manquants, barres obliques inverses incorrectes dans les chaînes, etc.), cela affiche un message utile de Nice contenant la ligne et le numéro de colonne où l'erreur JSON a été trouvée.
Cependant, pour d'autres types d'erreur JSON (y compris le classique "utiliser une virgule sur le dernier élément d'une liste", mais aussi d'autres choses comme la majuscule vrai/faux), la sortie de Python est simplement:
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
Pour ce type de ValueError, comment obtenez-vous que Python vous indique où se trouve l'erreur dans le fichier JSON?
J'ai constaté que le module simplejson
génère davantage d'erreurs descriptives dans les cas où le module intégré json
est vague. Par exemple, dans le cas d'une virgule après le dernier élément d'une liste:
json.loads('[1,2,]')
....
ValueError: No JSON object could be decoded
ce qui n'est pas très descriptif. La même opération avec simplejson
:
simplejson.loads('[1,2,]')
...
simplejson.decoder.JSONDecodeError: Expecting object: line 1 column 5 (char 5)
Beaucoup mieux! De même pour d'autres erreurs courantes telles que la majuscule True
.
Vous ne pourrez pas obtenir de python pour vous dire où le JSON est incorrect. Vous devrez utiliser un linter en ligne quelque part comme this
Cela vous montrera une erreur dans le JSON que vous essayez de décoder.
Vous pouvez essayer la bibliothèque rson trouvée ici: http://code.google.com/p/rson/ . Je le trouve aussi sur PYPI: https://pypi.python.org/pypi/rson/0.9 afin que vous puissiez utiliser easy_install ou pip pour l'obtenir.
pour l'exemple donné par tom:
>>> rson.loads('[1,2,]')
...
rson.base.tokenizer.RSONDecodeError: Unexpected trailing comma: line 1, column 6, text ']'
RSON est conçu pour être un sur-ensemble de JSON, afin de pouvoir analyser les fichiers JSON. Il a également une syntaxe alternative qui est beaucoup plus agréable pour les humains à regarder et éditer. Je l'utilise assez souvent pour les fichiers d'entrée.
En ce qui concerne la capitalisation des valeurs booléennes: il apparaît que rson lit les booléens mal capitalisés sous forme de chaînes.
>>> rson.loads('[true,False]')
[True, u'False']
J'ai eu un problème similaire et c'était dû à une seule citation. Le standard JSON ( http://json.org ) parle uniquement de l'utilisation de doubles guillemets; il est donc normal que la bibliothèque python json
ne prenne en charge que les guillemets doubles.
Pour ma version particulière de ce problème, je suis allé de l'avant et ai recherché la déclaration de fonction de load_json_file(path)
dans le fichier packaging.py
, puis j'ai inséré une ligne print
dans ce fichier:
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 cette façon, le contenu du fichier json serait imprimé avant de saisir le test, et ainsi, même avec mes connaissances en Python à peine existantes, je pouvais rapidement comprendre pourquoi ma configuration ne pouvait pas lire le fichier json.
.__ (c’est parce que j’avais configuré mon éditeur de texte pour écrire une nomenclature UTF-8… stupide)
Mentionnons simplement ceci parce que, même si ce n’était peut-être pas une bonne réponse au problème spécifique du PO, c’était une méthode assez rapide pour déterminer la source d’un bogue très oppressant. Et je parie que beaucoup de gens tomberont sur cet article qui recherchent une solution plus verbeuse pour un MalformedJsonFileError: No JSON object could be decoded when reading …
. Cela pourrait donc les aider.
J'ai eu un problème similaire c'était mon code:
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
le problème était que j'avais oublié de file.close()
je l'ai fait et résolu le problème.
Quant à moi, mon fichier json est très volumineux. Lorsqu’il utilise json
en python, il obtient l’erreur ci-dessus.
Après avoir installé simplejson
par Sudo pip install simplejson
.
Et puis je l'ai résolu.
import json
import simplejson
def test_parse_json():
f_path = '/home/hello/_data.json'
with open(f_path) as f:
# j_data = json.load(f) # ValueError: No JSON object could be decoded
j_data = simplejson.load(f) # right
lst_img = j_data['images']['image']
print lst_img[0]
if __== '__main__':
test_parse_json()
Lorsque votre fichier est créé. Au lieu de créer un fichier dont le contenu est vide. Remplacer par:
json.dump({}, file)
Cliquez simplement sur le même problème et dans mon cas, le problème était lié à BOM
(marque d'ordre des octets) au début du fichier.
json.tool
refuserait de traiter même un fichier vide (entre accolades seulement) jusqu'à ce que je supprime la marque de nomenclature UTF.
Ce que j'ai fait c'est:
set nobomb
)Cela a résolu le problème avec json.tool. J'espère que cela t'aides!
La réponse acceptée est la plus simple pour résoudre le problème. Mais au cas où vous n'êtes pas autorisé à installer simplejson en raison de la politique de votre entreprise, je propose la solution ci-dessous pour résoudre le problème particulier de "en utilisant une virgule sur le dernier élément d'une liste" :
Créez une classe enfant "JSONLintCheck" à hériter de la classe "JSONDecoder" et substituez la méthode init de la classe "JSONDecoder" comme ci-dessous:
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 #!/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