Kod Pythona do ładowania danych z jakiegoś długiego skomplikowanego pliku JSON:
with open(filename, "r") as f:
data = json.loads(f.read())
(uwaga: najlepsza wersja kodu to:
with open(filename, "r") as f:
data = json.load(f)
ale oba wykazują podobne zachowanie)
W przypadku wielu typów błędów JSON (brak ograniczników, nieprawidłowe ukośniki odwrotne w ciągach znaków itp.) Powoduje to wyświetlenie miłego, pomocnego komunikatu zawierającego numer wiersza i kolumny, w których znaleziono błąd JSON.
Jednak w przypadku innych typów błędów JSON (w tym klasycznego „używania przecinka na ostatnim elemencie na liście”, ale także innych rzeczy, takich jak pisanie wielkimi literami prawda / fałsz), wynik Pythona to po prostu:
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
W przypadku tego typu wartości ValueError, w jaki sposób Python powie Ci, gdzie jest błąd w pliku JSON?
json.load(f)
zamiastjson.loads(f.read())
Odpowiedzi:
Zauważyłem, że
simplejson
moduł daje więcej błędów opisowych w wielu przypadkach, gdy wbudowanyjson
moduł jest niejasny. Na przykład w przypadku przecinka po ostatniej pozycji na liście:json.loads('[1,2,]') .... ValueError: No JSON object could be decoded
co nie jest zbyt opisowe. Ta sama operacja z
simplejson
:simplejson.loads('[1,2,]') ... simplejson.decoder.JSONDecodeError: Expecting object: line 1 column 5 (char 5)
Dużo lepiej! Podobnie jest w przypadku innych typowych błędów, takich jak kapitalizowanie
True
.źródło
json
biblioteka stdlib została zaktualizowana i podaje nowy format komunikatów o błędach. Jednak nie mam teraz czasu na śledzenie dokładnych wydań.Nie będziesz w stanie zmusić Pythona, aby powiedział ci, gdzie JSON jest nieprawidłowy. Trzeba będzie użyć LINTER Internecie gdzieś jak ten
Spowoduje to wyświetlenie błędu w pliku JSON, który próbujesz zdekodować.
źródło
Możesz wypróbować bibliotekę rson, którą znajdziesz tutaj: http://code.google.com/p/rson/ . Mam go również na PYPI: https://pypi.python.org/pypi/rson/0.9, więc możesz użyć easy_install lub pip, aby to uzyskać.
na przykład podany przez tom:
>>> rson.loads('[1,2,]') ... rson.base.tokenizer.RSONDecodeError: Unexpected trailing comma: line 1, column 6, text ']'
RSON został zaprojektowany jako nadzbiór JSON, więc może analizować pliki JSON. Ma również alternatywną składnię, która jest znacznie przyjemniejsza dla ludzi do oglądania i edycji. Używam go dość często do plików wejściowych.
Co do kapitalizacji wartości boolowskich: wydaje się, że rson odczytuje niepoprawnie wielkie wartości logiczne jako ciągi znaków.
>>> rson.loads('[true,False]') [True, u'False']
źródło
Miałem podobny problem i było to spowodowane pojedynczymi cytatami. Standard JSON ( http://json.org ) mówi tylko o używaniu podwójnych cudzysłowów, więc musi być tak, że
json
biblioteka Pythona obsługuje tylko podwójne cudzysłowy.źródło
W przypadku mojej konkretnej wersji tego problemu przeszukałem deklarację funkcji
load_json_file(path)
wpackaging.py
pliku, a następnie przemyciłemprint
do niej wiersz: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))
W ten sposób wydrukowałby zawartość pliku json przed wejściem do try-catch, iw ten sposób - nawet przy mojej ledwo istniejącej wiedzy o Pythonie - mogłem szybko zorientować się, dlaczego moja konfiguracja nie mogła odczytać pliku json.
(To dlatego, że skonfigurowałem mój edytor tekstu do pisania BOM UTF-8… głupi)
Wspomnę tylko o tym, ponieważ choć może nie była to dobra odpowiedź na konkretny problem PO, była to raczej szybka metoda określenia źródła bardzo uciążliwego błędu. I założę się, że wiele osób natknie się na ten artykuł, którzy szukają bardziej szczegółowego rozwiązania dla
MalformedJsonFileError: No JSON object could be decoded when reading …
. To może im pomóc.źródło
with open(fn) as f
), obsługuje on zamknięcie pliku w wyjątkowych sytuacjach. en.wikibooks.org/wiki/Python_Programming/…Jeśli chodzi o mnie, mój plik json jest bardzo duży, gdy używa się wspólnego
json
w Pythonie, otrzymuje powyższy błąd.Po zainstalowaniu
simplejson
przezsudo pip install simplejson
.A potem to rozwiązałem.
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 __name__ == '__main__': test_parse_json()
źródło
Miałem podobny problem, to był mój kod:
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
problem polegał na tym, że zapomniałem o
file.close()
tym, że to zrobiłem i naprawiłem problem.źródło
with open(fn) as f
), obsługuje on zamknięcie pliku w wyjątkowych sytuacjach. en.wikibooks.org/wiki/Python_Programming/…Zaakceptowana odpowiedź jest najłatwiejsza do rozwiązania problemu. Ale w przypadku, gdy nie możesz zainstalować simplejson ze względu na politykę Twojej firmy, proponuję poniższe rozwiązanie, aby rozwiązać konkretny problem „używania przecinka na ostatniej pozycji na liście” :
Utwórz klasę podrzędną „JSONLintCheck”, aby dziedziczyć z klasy „JSONDecoder” i nadpisać metodę init klasy „JSONDecoder”, jak poniżej:
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
źródło
Po prostu trafiłem na ten sam problem iw moim przypadku problem był związany z
BOM
(znacznikiem kolejności bajtów) na początku pliku.json.tool
odmówiłby przetwarzania nawet pustego pliku (tylko nawiasów klamrowych), dopóki nie usunę znaku BOM UTF.To, co zrobiłem, to:
set nobomb
)To rozwiązało problem z json.tool. Mam nadzieję że to pomoże!
źródło
Kiedy tworzony jest plik. Zamiast tworzyć plik z zawartością jest pusty. Zamienić:
źródło
Możesz użyć cjson , który twierdzi, że jest do 250 razy szybszy niż implementacje w czystym Pythonie, biorąc pod uwagę, że masz "jakiś długi, skomplikowany plik JSON" i prawdopodobnie będziesz musiał go uruchomić kilka razy (dekodery zawodzą i zgłaszają pierwszy błąd tylko spotkanie).
źródło