JSONDecodeError: очікуване значення: рядок 1, стовпець 1 (char 0)


259

Я отримую помилку Expecting value: line 1 column 1 (char 0)при спробі розшифрувати JSON.

URL-адреса, яку я використовую для виклику API, працює добре у веб-переглядачі, але видає цю помилку, коли робиться через запит на згортання. Далі наведено код, який я використовую для запиту 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()?
Martijn Pieters

4
Ще одне: навіщо використовувати, simplejsonколи ви можете просто використовувати stdlib json(це та сама бібліотека, що іsimplejson )?
Martijn Pieters

3
Це порожня рядок. Ваш web_fetch() дзвінок не вдався.
Martijn Pieters

1
Так, я рекомендую вам використовувати щось простіше у використанні, ніж pycurl. requestsпропонує набагато простіший API, особливо якщо мова йде про налагодження того, що відбувається. Якщо ви спеціально не маєте новішої версії simplejsonбібліотеки, просто дотримуйтесь json, це заощадить залежність від управління.
Martijn Pieters

1
це response_jsonповернене значення .json()? Тоді ви вже розшифрували дані і більше не потрібно їх використовувати json.loads(). responseрозшифрував це для вас.
Martijn Pieters

Відповіді:


124

Щоб узагальнити розмову в коментарях:

  • Немає необхідності користуватися 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. Дивно.
rayu

@Rayu: запити використовуватимуться,simplejson якщо вони доступні; деякі люди хочуть використовувати останню версію simplejson, а не ту, яка в комплекті з stdlib Python.
Martijn Pieters

5
"Немає необхідності використовувати simplejson-бібліотеку. Ця ж бібліотека включена в Python як і модуль json." ... Я з повагою не погоджуюся. simplejsonвикористовує вбудований jsonпід капотом, але дає більше описових помилок. У цьому випадку використання jsonпросто дасть вам загальне значення ValueError: No JSON object could be decoded.
BoltzmannBrain

2
Чи може це бути викликано абортом або неповним json? Я отримую це випадково раз у раз, не знаючи, як це відтворити.
Крістоф Руссі

2
@ChristopheRoussy: так, це справа в питанні (ОП отримало порожню u'' відповідь). Ваш JSONDecodeErrorрозповідає, що багато даних було успішно проаналізовано до того, як вони натрапили на помилку; це може бути тому, що в цій точці є недійсні дані (неправильно сформований або пошкоджений документ JSON) або тому, що дані були усічені.
Martijn Pieters

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 також не працює.
Martijn Pieters

JSONDecodeError: Expecting value: line 1 column 1 (char 0)конкретно виникає, коли порожня рядок передається до декодування json
wesinat0r

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

34

З requestslib JSONDecodeErrorможе статися, коли у вас є код помилки http, як 404, і спробувати розібрати відповідь як JSON!

Спершу потрібно перевірити наявність 200 (ОК) або дозволити помилково підвищити цей показник. Я б хотів, щоб це не вдалося з менш виразним повідомленням про помилку.

ПРИМІТКА : як зазначено в коментарях Martijn Pieters, сервери можуть відповідати JSON у разі помилок (це залежить від реалізації), тому перевірка Content-Typeзаголовка є більш надійною.


Вибачте за старий коментар, але ви могли посилатися на приклад? Я намагаюся перейняти свої навички від "виконувати дії", до "спроби виконати дію, повернути відповідь, відповідно реагувати".
dcclassics

@dcclassics: Приклад: він не працює на стороні сервера, і сервер відповідає, показуючи сторінку помилки (HTML) замість відповіді з JSON, тому код, що аналізує відповідь, спробує прочитати JSON, але не вдасться в тегах HTML.
Крістоф Руссі

1
Сервери можуть і включати тіла JSON у відповіді на помилки. Це не просто 200 ОК відповідей. Ви хочете перевірити заголовок Content-Type.
Martijn Pieters

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 (). Використовуйте заміну ():

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

У мене була така ж проблема із запитами (бібліотека пітона). Це сталося саме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 колонки 1 json нічого не було. Завжди добре перевірити, чи є код статусу запиту таким, яким ви його очікуєте.
thposs

0

Якщо ви користувач Windows, API Tweepy може створити порожній рядок між об'єктами даних. Через цю ситуацію ви можете отримати помилку "JSONDecodeError: Очікуючи значення: рядок 1, стовпець 1 (char 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, помилка. Значення) від None


Я не думаю, що порожні рядки не є проблемою. У ній чітко зазначено, що помилка знаходиться у колонці 1 рядка 1. Я думаю, що це рішення працює, оскільки це видалення BOM з файлу. Ви можете швидко перевірити це: 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.