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)

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 = {}

Во время отладки в моем коде я звонил, 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

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

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


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

Это было проблемой для меня. Код состояния был 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')

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


Я не думаю, что пустые строки являются проблемой. В нем четко указано, что ошибка находится в строке 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"

0

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

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

requests.post(url, data=json.dumps(data))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.