Ошибка Python ValueError: невозможно декодировать объект JSON (прерывистый) - PullRequest
0 голосов
/ 28 апреля 2018

Получение ошибки с помощью следующего кода. Однако иногда это работает, а иногда нет. Я проверил данные с помощью JSONLint. Я пытался декодировать / кодировать данные на основе ответов на аналогичные вопросы об ошибках, а также пытался сделать то же самое с помощью модуля кодеков. Чего я не понимаю, так это того, почему иногда он работает нормально, а в других случаях выдает ошибку.

import requests
import json
import codecs

response = requests.get("https://api.weather.gov/alerts/active")
print(response.status_code)

with open ('data.json', 'w') as file:
    file.write(response.content)

myFile = open('data.json', 'r')
myObject = myFile.read()
u = myObject.decode('utf-8-sig')
myObject = u.encode('utf-8')
myFile.encoding
myFile.close()
myData = json.loads(myObject, 'utf-8') 

#myData=json.loads(codecs.open(myObject,'r', 'utf-8'))

Образец данных JSON можно найти в другом вопросе, который я задал здесь .

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Проблема в том, что ваш JSON на самом деле недействителен.

Взяв пример из вашего другого вопроса , вы можете вставить его в валидатор JSON, например этот , и посмотреть на проблему: в строке 35 после последней запятой стоит запятая значение в массиве. Это не законный JSON . Поэтому никакой анализатор JSON не сможет его проанализировать.

Это не имеет ничего общего с кодировкой символов. Так что добавление дополнительных вызовов encode и decode и добавление дополнительных библиотек, чтобы сделать это еще больше раз, не поможет. Вы правильно декодировали байты в текст, но этот текст не является допустимым JSON.


Почему это случается иногда, но не в других случаях? Предположительно (только на основании имени конечной точки), что API собирает оповещения из разных мест на их бэкэнде, и иногда одно из этих оповещений кодируется неправильно, но в большинстве случаев все нормально (или их нет). ). Кто знает? Это не ваша ошибка, чтобы исправить; это их.

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


Что вы можете сделать в это время? Что ж, если вы можете просто try / except JSONDecodeError: и пропустить случайное плохое значение, это, вероятно, лучший ответ, пока они не исправят ситуацию. Если наличие неполных данных делает вашу программу недействительной, это не очень хорошо. В частности, в этом случае это может означать, что вы не получаете данных за все время, пока какое-либо важное предупреждение было активным, поэтому вы никогда его не увидите.

Есть "неаккуратные" JSON-декодеры, которые вы можете попробовать. Как правило, это плохая идея, потому что легко в конечном итоге молча неправильно декодировать что-то неправильно и получать данные мусора в вашу коллекцию. Это также означает, что большинство таких проектов заброшены, как только автор решит, что это плохая идея. Но люди продолжают писать новые, поэтому, если вы действительно хотите, вы можете найти и найти один.

Если ошибки в их JSON непротиворечивы , и вы можете решить, как их описать, вы сможете написать специальный неаккуратный декодер "JSON", который обрабатывает именно эти ошибки, или препроцессор, который исправляет эти ошибки перед декодированием. Это будет нетривиально и, возможно, немного уродливо, но тогда, может быть, должно быть некрасивым - каждый раз, когда вы его читаете, вам будет напоминать, проверял ли провайдер свою ошибку, чтобы вы могли бросить из этого уродливого кода. Во всяком случае, никто не может понять, являются ли их ошибки непротиворечивыми, а затем написать код, который с ними справляется, без гораздо большего, чем просто один пример. И, наверное, никто не хочет пройти через весь беспорядок недопустимого JSON для вас. Поэтому, если вы хотите пойти по этому пути, вам придется попытаться сделать это самостоятельно (но, конечно, вы всегда можете задать новый вопрос, если застряли со всеми соответствующими деталями).

0 голосов
/ 28 апреля 2018

Почему вы держите код таким сложным? Вы можете просто сделать:

obj = requests.get("https://api.weather.gov/alerts/active").json()

Объект json автоматически декодируется для вас в pythonic dict. Кажется, что он работает последовательно с python 2.7.14 и 3.6.5.

...