JSONDecodeError: Ожидаемое значение: строка 1, столбец 1 (символ 0)

260

Я получаю сообщение об ошибке Expecting value: line 1 column 1 (char 0)при попытке декодирования JSON.

URL, который я использую для вызова API, прекрасно работает в браузере, но выдает эту ошибку при выполнении запроса curl. Ниже приведен код, который я использую для запроса curl.

Ошибка происходит в return simplejson.loads(response_json)

    response_json = self.web_fetch(url)
    response_json = response_json.decode('utf-8')
    return json.loads(response_json)


def web_fetch(self, url):
        buffer = StringIO()
        curl = pycurl.Curl()
        curl.setopt(curl.URL, url)
        curl.setopt(curl.TIMEOUT, self.timeout)
        curl.setopt(curl.WRITEFUNCTION, buffer.write)
        curl.perform()
        curl.close()
        response = buffer.getvalue().strip()
        return response

Полная трассировка:

Выслеживать:

File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Users/nab/Desktop/pricestore/pricemodels/views.py" in view_category
  620.     apicall=api.API().search_parts(category_id= str(categoryofpart.api_id), manufacturer = manufacturer, filter = filters, start=(catpage-1)*20, limit=20, sort_by='[["mpn","asc"]]')
File "/Users/nab/Desktop/pricestore/pricemodels/api.py" in search_parts
  176.         return simplejson.loads(response_json)
File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/simplejson/__init__.py" in loads
  455.         return _default_decoder.decode(s)
File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/simplejson/decoder.py" in decode
  374.         obj, end = self.raw_decode(s)
File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/simplejson/decoder.py" in raw_decode
  393.         return self.scan_once(s, idx=_w(s, idx).end())

Exception Type: JSONDecodeError at /pricemodels/2/dir/
Exception Value: Expecting value: line 1 column 1 (char 0)
user1328021
источник
2
И последнее, но не менее важное: что print repr(response_json)говорит вам , что вас передают .loads()?
Мартин Питерс
4
Еще один: зачем использовать, simplejsonкогда вы можете просто использовать stdlib json(который является той же библиотекой, что иsimplejson )?
Мартин Питерс
3
Это пустая строка. Ваш web_fetch() звонок не удался.
Мартин Питерс
1
Да, я рекомендую вам использовать что-то более простое в использовании, чем pycurl. requestsпредлагает гораздо более простой API, особенно когда дело доходит до отладки происходящего. Если вам не требуется более новая версия simplejsonбиблиотеки, просто придерживайтесь ее json, сохраняя зависимость от управления.
Мартин Питерс
1
это response_jsonвозвращаемое значение .json()? Тогда у вас уже есть декодированные данные, и вам больше не нужно их использовать json.loads(). responseрасшифровал это для вас.
Мартин Питерс

Ответы:

125

Подводя итог разговора в комментариях:

  • Нет необходимости использовать simplejsonбиблиотеку, в состав Python входит та же библиотека, что и в jsonмодуле.

  • Нет необходимости декодировать ответ из UTF8 в Unicode, метод simplejson/ json .loads()может обрабатывать данные в кодировке UTF8.

  • pycurlимеет очень архаичный API. Если у вас нет особых требований для его использования, есть лучший выбор.

requestsпредлагает наиболее дружественный API, включая поддержку JSON. Если можете, замените ваш звонок на:

import requests

return requests.get(url).json()
Мартейн Питерс
источник
93
Я получаю эту же ошибку, используя requests! След, кажется, предполагает, что requestsиспользует complexjson, который использует simplejson. Weird.
раю
@Rayu: запросы будут использовать,simplejson если доступны; некоторые люди хотят использовать последнюю версию simplejson, а не ту, что входит в комплект Python stdlib.
Мартин Питерс
5
«Нет необходимости использовать библиотеку simplejson, в Python входит та же библиотека, что и в модуле json.» ... Я с уважением не согласен. simplejsonиспользует встроенный jsonпод капотом, но дает больше описательных ошибок. В этом случае использование jsonпросто даст вам общий ValueError: No JSON object could be decoded.
BoltzmannBrain
2
Может ли это быть вызвано прерыванием или неполным JSON? Время от времени я получаю это случайно, не зная, как это воспроизвести.
Кристоф Русси
2
@ChristopheRoussy: да, это скорее вопрос (ОП получил пустой u'' ответ). Ваш JSONDecodeErrorговорит вам, что много данных было успешно проанализировано, прежде чем он столкнулся с ошибкой; это может быть связано с тем, что в этой точке есть недопустимые данные (искаженный или поврежденный документ JSON) или из-за того, что данные были усечены.
Мартин Питерс
64

Проверьте тело данных ответа, присутствуют ли фактические данные, и дамп данных выглядит хорошо отформатированным.

В большинстве случаев ваша json.loads- JSONDecodeError: Expecting value: line 1 column 1 (char 0)ошибка происходит из - за:

  • цитирование не по JSON
  • Вывод XML / HTML (то есть строка, начинающаяся с <), или
  • несовместимая кодировка символов

В конечном итоге ошибка говорит о том, что в самой первой позиции строка уже не соответствует JSON.

Таким образом, если синтаксический анализ завершится неудачно, несмотря на наличие тела данных, которое на первый взгляд выглядит как JSON , попробуйте заменить кавычки тела данных:

import sys, json
struct = {}
try:
  try: #try parsing to dict
    dataform = str(response_json).strip("'<>() ").replace('\'', '\"')
    struct = json.loads(dataform)
  except:
    print repr(resonse_json)
    print sys.exc_info()

Примечание: кавычки в данных должны быть правильно экранированы

Лоренц Ло Зауэр
источник
4
В комментариях было ясно, что ОП получил пустой ответ. Так как requests.get(url).json()Just Works, JSON также не является уродливым.
Мартин Питерс
JSONDecodeError: Expecting value: line 1 column 1 (char 0)в частности происходит, когда в
декодер
JSONDecodeError: Expecting value: line 1 column 1 (char 0)также происходит, когда первая строка в ответе json неверна. Пример ответ от запуска в az cliкоманде находится ["WARNING: The default kind for created storage account will change to 'StorageV2' from 'Storage' in the future", '{',. Это дало мне ошибку, которая привела меня сюда. Остальная часть ответа является допустимым объектом json. Просто эта первая строка ломает вещи.
SeaDude
35

С requestsбиблиотекой lib это JSONDecodeErrorможет произойти, если у вас есть код ошибки http, например 404, и вы пытаетесь проанализировать ответ как JSON!

Вы должны сначала проверить на 200 (ОК) или позволить ему подняться при ошибке, чтобы избежать этого случая. Жаль, что это не удалось с менее загадочным сообщением об ошибке.

ПРИМЕЧАНИЕ : как отметил Martijn Pieters в комментариях, серверы могут отвечать JSON в случае ошибок (это зависит от реализации), поэтому проверка Content-Typeзаголовка более надежна.

Кристоф Русси
источник
Извините за старый комментарий, но не могли бы вы дать ссылку на пример? Я пытаюсь перенять свои навыки от «выполнить действие» до «попытаться выполнить действие, дать ответ, отреагировать соответственно».
dcclassics
@dcclassics: Пример: происходит сбой на стороне сервера, и сервер отвечает, показывая страницу с ошибкой (HTML) вместо ответа с JSON, поэтому при синтаксическом анализе ответа будет пытаться прочитать JSON, но произойдет сбой в тегах HTML.
Кристоф Русси
1
Серверы могут и действительно включают тела JSON в сообщения об ошибках. Это не просто 200 хороших ответов. Вы хотите проверить заголовок Content-Type.
Мартин Питерс
29

Я думаю , что стоит отметить , что в тех случаях , когда вы разбираете содержимое самого файла JSON - здравомыслие проверка может быть полезна для того , чтобы вы на самом деле ссылаться json.loads()на содержимом файла, в отличии от пути к файлу этого JSON :

json_file_path = "/path/to/example.json"

with open(json_file_path, 'r') as j:
     contents = json.loads(j.read())

Я немного смущен, чтобы признать, что это может иногда случаться:

contents = json.loads(json_file_path)
Алекс
источник
Ну .. Иногда это случается. Спасибо Это сработало, кстати.
Сачин Кумар
Я думаю, что в этом случае следует использовать json.load()вместо этого.
Кодди
13

Проверьте формат кодировки вашего файла и используйте соответствующий формат кодирования при чтении файла. Это решит вашу проблему.

with open("AB.json", encoding='utf-8', errors='ignore') as json_data:
     data = json.load(json_data, strict=False)
Раминени Рави Теджа
источник
3
Это сработало для меня с небольшим изменением encoding='utf-8', так что я полагаю, иногда вам нужно попробовать несколько вещей.
RobertMyles
9

Часто это происходит потому, что строка, которую вы пытаетесь проанализировать, пуста:

>>> import json
>>> x = json.loads("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Вы можете исправить, проверив, json_stringпусто ли заранее:

import json

if json_string:
    x = json.loads(json_string)
else:
    // Your logic here
    x = {}
Алекс W
источник
Во время отладки в моем коде я звонил, response.read()а затем был встревожен, когда другой вызов закончился Expecting value: line 1и т. Д. Удалил оператор отладки и проблема была решена.
Джо
Для отладки вы также можете использовать этот замечательный веб-сайт jsonlint.com
Roelant,
4

Там могут быть встроены 0, даже после вызова decode (). Используйте replace ():

import json
struct = {}
try:
    response_json = response_json.decode('utf-8').replace('\0', '')
    struct = json.loads(response_json)
except:
    print('bad json: ', response_json)
return struct
Bryan
источник
2

У меня была именно эта проблема с использованием запросов. Спасибо Кристофу Русси за его объяснение.

Для отладки я использовал:

response = requests.get(url)
logger.info(type(response))

Я получал ответ 404 от API.

Келси Брэйдвуд
источник
1
Это может быть упрощено до response.status_codeили print(response.status_code).
TitanFighter
1

У меня была такая же проблема с запросами (библиотека python). Это случилось с accept-encodingзаголовком.

Это было установлено следующим образом: 'accept-encoding': 'gzip, deflate, br'

Я просто удалил его из запроса и перестал получать ошибку.

Сеу Мадруга
источник
1

Для меня это не было использование аутентификации в запросе.

Neel0507
источник
1

Для меня это был ответ сервера чем-то отличным от 200, и ответ не был отформатирован в json. Я закончил этим до разбора json:

# this is the https request for data in json format
response_json = requests.get() 

# only proceed if I have a 200 response which is saved in status_code
if (response_json.status_code == 200):  
     response = response_json.json() #converting from json to dictionary using json library
FastGTR
источник
Это было проблемой для меня. Код состояния был 500 (внутренняя ошибка сервера) вместо 200, поэтому json не был возвращен, и поэтому в строке 1 col 1 json ничего не было. Всегда полезно убедиться, что код состояния запроса соответствует ожидаемому.
thposs
1

Я столкнулся с той же проблемой, когда печатал строку json, открытую из файла json, обнаружил, что строка json начинается с «ï» ¿, что при некотором повторном поиске происходит из-за того, что файл по умолчанию декодируется с помощью UTF-8, и изменив кодировку на utf-8-sig, разметка удаляется и без проблем загружает json:

open('test.json', encoding='utf-8-sig')
user9571515
источник
0

Если вы пользователь Windows, Tweepy API может создать пустую строку между объектами данных. Из-за этой ситуации вы можете получить сообщение об ошибке «JSONDecodeError: Ожидаемое значение: строка 1, столбец 1 (символ 0)». Чтобы избежать этой ошибки, вы можете удалить пустые строки.

Например:

 def on_data(self, data):
        try:
            with open('sentiment.json', 'a', newline='\n') as f:
                f.write(data)
                return True
        except BaseException as e:
            print("Error on_data: %s" % str(e))
        return True

Ссылка: API потока Twitter выдает JSONDecodeError («Ожидаемое значение», s, err.value) из None

drorhun
источник
Я не думаю, что пустые строки являются проблемой. В нем четко указано, что ошибка находится в строке 1 столбца 1. Я думаю, что этот обходной путь работает, поскольку он удаляет спецификацию из файла. Вы можете быстро проверить это: 1. Проверьте размер исходного файла (щелкните правой кнопкой мыши> Свойства), он может быть 134,859 байт. 2. Откройте исходный файл с помощью Notepad ++ 3. Измените кодировку с «UTF-8-BOM» на « UTF-8" . Сохранить 4. Проверьте размер еще раз. Это может быть 134,856 (3 байта меньше)
Алекс 75
0

Просто проверьте, имеет ли запрос код состояния 200. Так, например:

if status != 200:
    print("An error has occured. [Status code", status, "]")
else:
    data = response.json() #Only convert to Json when status is OK.
    if not data["elements"]:
        print("Empty JSON")
    else:
        "You can extract data here"
Wout VC
источник
0

Я получил такую ​​ошибку в ответе веб-API на основе Python .text, но он привел меня сюда, так что это может помочь другим с подобной проблемой (очень трудно отфильтровать ответ и запросить проблемы в поиске при использовании requests..)

Использование json.dumps()по запросу data аргумента arg для создания правильно экранированной строки JSON, прежде чем POSTing решит проблему для меня

requests.post(url, data=json.dumps(data))
ti7
источник