Отображение лучшего сообщения об ошибке, чем "Нет объекта JSON можно декодировать"

Код Python для загрузки данных из некоторого длинного сложного файла JSON:

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

(примечание: лучшая версия кода должна быть:

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

но оба имеют сходное поведение)

Для многих типов ошибок JSON (отсутствующие разделители, неправильные обратные косые черты в строках и т.д.) это печатает полезное сообщение, содержащее строку и номер столбца, где была обнаружена ошибка JSON.

Однако для других типов ошибок JSON (включая классический "использование запятой по последнему элементу в списке", но также и других вещей, таких как capizing true/false), вывод Python:

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

Для этого типа ValueError, как вы получаете Python, чтобы сообщить вам, где ошибка в файле JSON?

Ответ 1

Я обнаружил, что модуль simplejson дает больше описательных ошибок во многих случаях, когда встроенный модуль json является неопределенным. Например, для случая наличия запятой после последнего элемента в списке:

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

который не очень описателен. Эта же операция с simplejson:

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

Гораздо лучше! Аналогично для других распространенных ошибок, например, для заглавной буквы True.

Ответ 2

Вы не сможете заставить python рассказать вам, где JSON неверен. Вам нужно будет использовать linter онлайн где-нибудь, например this

Это покажет вам ошибку в JSON, который вы пытаетесь декодировать.

Ответ 3

Вы можете попробовать библиотеку rson, найденную здесь: http://code.google.com/p/rson/. Я также на PYPI: https://pypi.python.org/pypi/rson/0.9, чтобы вы могли использовать easy_install или pip для его получения.

для примера, данного tom:

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

RSON - это надстройка JSON, поэтому он может анализировать файлы JSON. Он также имеет альтернативный синтаксис, который лучше much для людей, чтобы смотреть и редактировать. Я использую его довольно много для входных файлов.

Что касается капитализации булевых значений: кажется, что rson неправильно считывает заглавные буквы в виде строк.

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

Ответ 4

У меня была аналогичная проблема, и это было связано с одиночными комментариями. Стандарт JSON (http://json.org) говорит только об использовании двойных кавычек, поэтому должно быть установлено, что библиотека python json поддерживает только двойные кавычки.

Ответ 5

Для моей конкретной версии этой проблемы я пошел дальше и искал объявление функции load_json_file(path) в файле packaging.py, затем контрабандировал строку print в нее:

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))

Таким образом, он будет печатать содержимое json файла перед входом в try-catch, и таким образом - даже с моими едва ли имеющимися знаниями Python - мне удалось быстро выяснить, почему моя конфигурация не может прочитать json файл.
(Это было потому, что я создал свой текстовый редактор для написания спецификации UTF-8... глупо)

Просто упомянем об этом, потому что, хотя, возможно, и не очень хороший ответ на конкретную проблему OP, это был довольно быстрый метод определения источника очень угнетающей ошибки. И я уверен, что многие люди наткнутся на эту статью, которая ищет более подробное решение для MalformedJsonFileError: No JSON object could be decoded when reading …. Это может помочь им.

Ответ 6

У меня была аналогичная проблема, это был мой код:

    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

Проблема была в том, что я забыл file.close() Я сделал это и исправил проблему.

Ответ 7

Вы можете использовать cjson, который утверждает, что он в 250 раз быстрее, чем реализации pure-python, учитывая, что у вас есть "некоторые длинный сложный файл JSON", и вам, вероятно, придется запускать его несколько раз (декодеры терпят неудачу и сообщают о первой ошибке, с которой они сталкиваются).