JSONDecodeError: Oczekiwana wartość: wiersz 1 kolumna 1 (znak 0)

258

Expecting value: line 1 column 1 (char 0)Podczas próby dekodowania JSON pojawia się błąd .

Adres URL, którego używam do wywołania interfejsu API, działa dobrze w przeglądarce, ale wyświetla ten błąd po wykonaniu żądania curl. Poniżej znajduje się kod, którego używam do żądania curl.

Błąd występuje o 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

Pełny Traceback:

Traceback:

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)
użytkownik1328021
źródło
2
Na koniec, co mówi print repr(response_json)ci, że jesteś przekazywany .loads()?
Martijn Pieters
4
Jeszcze jedno: simplejsonpo co korzystać, skoro można po prostu użyć stdlib json(czyli tej samej biblioteki cosimplejson )?
Martijn Pieters
3
To jest pusty ciąg. Twoje web_fetch() połączenie nie powiodło się.
Martijn Pieters
1
Tak, polecam użyć czegoś łatwiejszego w użyciu niż pycurl. requestsoferuje znacznie łatwiejszy interfejs API, szczególnie jeśli chodzi o debugowanie tego, co się dzieje. Chyba że musisz mieć nowszą wersję simplejsonbiblioteki, po prostu trzymaj się json, oszczędzasz zależność do zarządzania.
Martijn Pieters
1
jest response_jsonwartością zwracaną .json()? Następnie masz już zdekodowane dane i nie musisz json.loads()już ich używać . responserozszyfrowałem to dla ciebie.
Martijn Pieters

Odpowiedzi:

123

Podsumowując rozmowę w komentarzach:

  • Nie ma potrzeby korzystania z simplejsonbiblioteki, ta sama biblioteka jest dołączona do Pythona jako jsonmoduł.

  • Nie ma potrzeby dekodowania odpowiedzi z UTF8 na Unicode, metoda simplejson/ json .loads()może obsługiwać dane zakodowane w UTF8 natywnie.

  • pycurlma bardzo archaiczny interfejs API. O ile nie ma określonych wymagań dotyczących korzystania z niego, istnieją lepsze opcje.

requestsoferuje najbardziej przyjazny interfejs API, w tym obsługę JSON. Jeśli możesz, zamień swoje połączenie na:

import requests

return requests.get(url).json()
Martijn Pieters
źródło
93
Otrzymuję ten sam błąd za pomocą requests! Ślad wydaje się sugerować, że requestsużywa complexjson, który używa simplejson. Dziwne.
rayu
@Rayu: wnioski będą używane,simplejson jeśli są dostępne; niektórzy ludzie wolą korzystać z najnowszej wersji simplejson zamiast z pakietu stdlib w Pythonie.
Martijn Pieters
5
„Nie ma potrzeby korzystania z biblioteki simplejson, ta sama biblioteka jest zawarta w Pythonie jako moduł json.” ... Z szacunkiem się nie zgadzam. simplejsonużywa wbudowanego jsonpod maską, ale daje więcej opisowych błędów. W takim przypadku użycie jsondałoby po prostu ogólny ValueError: No JSON object could be decoded.
BoltzmannBrain
2
Czy może to być spowodowane przerwaniem lub niepełnym plikiem Json? Od czasu do czasu dostaję to losowo, nie jestem pewien, jak to odtworzyć.
Christophe Roussy
2
@ChristopheRoussy: tak, to raczej sedno pytania (OP otrzymał pustą u'' odpowiedź). Twój JSONDecodeErrorpowie Ci dużo danych został pomyślnie przeanalizowany, zanim wpadł błędu; może to być spowodowane tym, że w tym momencie istnieją nieprawidłowe dane (zniekształcony lub uszkodzony dokument JSON) lub ponieważ dane zostały obcięte.
Martijn Pieters
64

Sprawdź treść danych odpowiedzi, czy rzeczywiste dane są obecne, a zrzut danych wydaje się być dobrze sformatowany.

W większości przypadków json.loads- JSONDecodeError: Expecting value: line 1 column 1 (char 0)błąd jest spowodowany:

  • cytowanie niezgodne z JSON
  • Dane wyjściowe XML / HTML (czyli ciąg rozpoczynający się od <) lub
  • niekompatybilne kodowanie znaków

Ostatecznie błąd mówi ci, że na pierwszej pozycji łańcuch już nie jest zgodny z JSON.

W związku z tym, jeśli parsowanie nie powiedzie się, mimo że ciało danych wygląda JSON jak na pierwszy rzut oka, spróbuj zastąpić cudzysłowy ciała danych:

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

Uwaga: cytaty w danych muszą być odpowiednio oznaczone znakami ucieczki

Lorenz Lo Sauer
źródło
4
W komentarzach było jasne, że OP otrzymało pustą odpowiedź. Od requests.get(url).json()Just Works JSON również nie jest zniekształcony.
Martijn Pieters
JSONDecodeError: Expecting value: line 1 column 1 (char 0)szczególnie występuje, gdy pusty ciąg jest przekazywany do dekodowania json
wesinat0r
JSONDecodeError: Expecting value: line 1 column 1 (char 0)dzieje się tak również, gdy pierwszy wiersz w odpowiedzi Json jest nieprawidłowy. Przykładowa odpowiedź z uruchomienia az clipolecenia to ["WARNING: The default kind for created storage account will change to 'StorageV2' from 'Storage' in the future", '{',. To dało mi błąd, który mnie tu doprowadził. Reszta odpowiedzi JEST poprawnym obiektem Json. Tylko ta pierwsza linia coś psuje.
SeaDude
34

Z requestslib JSONDecodeErrormoże się zdarzyć, gdy masz kod błędu HTTP, taki jak 404, i spróbuj przeanalizować odpowiedź jako JSON!

Najpierw sprawdź 200 (OK) lub pozwól, aby podniósł się w przypadku błędu, aby uniknąć tego przypadku. Żałuję, że nie powiodło się z mniej tajemniczym komunikatem błędu.

UWAGA : jak podał Martijn Pieters w komentarzach, serwery mogą odpowiadać za pomocą JSON w przypadku błędów (zależy to od implementacji), więc sprawdzanie Content-Typenagłówka jest bardziej niezawodne.

Christophe Roussy
źródło
Przepraszam za stary komentarz, ale czy możesz podać link do przykładu? Staram się przenieść moje umiejętności z „wykonywania akcji” na „próbę wykonania akcji, odpowiedzi zwrotnej, odpowiednio zareagować”.
dcclassics
@dcclassics: Przykład: nie działa po stronie serwera, a serwer odpowiada wyświetlając stronę błędu (HTML) zamiast odpowiedzi za pomocą JSON, więc kod analizujący odpowiedź będzie próbował odczytać JSON, ale zawiedzie w tagach HTML.
Christophe Roussy
1
Serwery mogą uwzględniać treści JSON w odpowiedziach na błędy. To nie tylko 200 odpowiedzi OK. Chcesz sprawdzić nagłówek Content-Type.
Martijn Pieters
29

Myślę, że to warto wspomnieć, że w przypadkach, gdy jesteś parsowania zawartość samego pliku JSON - testy sprawdzające mogą być przydatne w celu zapewnienia, że jesteś rzeczywiście powołując się json.loads()na zawartości pliku, w przeciwieństwie do ścieżki pliku tego JSON :

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

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

Jestem trochę zawstydzony przyznając, że czasem może się to zdarzyć:

contents = json.loads(json_file_path)
alex
źródło
Cóż .. Czasami się zdarza. Dzięki Działało btw.
Sachin Kumar
Myślę, że w takim przypadku należy użyć json.load()zamiast tego.
Coddy
13

Sprawdź format kodowania pliku i użyj odpowiedniego formatu kodowania podczas czytania pliku. Rozwiąże twój problem.

with open("AB.json", encoding='utf-8', errors='ignore') as json_data:
     data = json.load(json_data, strict=False)
Ramineni Ravi Teja
źródło
3
To zadziałało dla mnie z małą zmianą encoding='utf-8', więc przypuszczam, że czasami trzeba wypróbować kilka rzeczy.
RobertMyles,
9

Często dzieje się tak, ponieważ ciąg, który próbujesz przeanalizować, jest pusty:

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

Możesz temu zaradzić, sprawdzając, czy json_stringjest wcześniej pusty:

import json

if json_string:
    x = json.loads(json_string)
else:
    // Your logic here
    x = {}
Alex W.
źródło
Podczas debugowania w dalszej części mojego kodu dzwoniłem, response.read()a potem byłem przerażony, gdy wywołało to inne wywołanie Expecting value: line 1itp. Usunąłem instrukcję debugowania i problem został rozwiązany.
Joe
Aby debugować, możesz także użyć tej ładnej strony internetowej jsonlint.com
Roelant
4

Mogą być osadzone zera, nawet po wywołaniu decode (). Użyj 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
źródło
2

Miałem dokładnie ten problem przy użyciu żądań. Dzięki Christophe Roussy za jego wyjaśnienie.

Do debugowania użyłem:

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

Otrzymałem odpowiedź 404 z API.

Kelsie Braidwood
źródło
1
Można to uprościć do response.status_codelub print(response.status_code).
TitanFighter
1

Miałem ten sam problem z żądaniami (biblioteka python). To się stało accept-encodingnagłówek.

Ustawiono to w następujący sposób: 'accept-encoding': 'gzip, deflate, br'

Po prostu usunąłem go z żądania i przestałem otrzymywać błąd.

Seu Madruga
źródło
1

Dla mnie nie używał uwierzytelnienia w żądaniu.

Neel0507
źródło
1

Dla mnie serwer odpowiadał czymś innym niż 200 i odpowiedź nie była sformatowana w formacie json. Skończyło się na tym przed analizą 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
źródło
To był dla mnie problem. Kod stanu to 500 (wewnętrzny błąd serwera) zamiast 200, więc nie zwrócono żadnego JSON, a zatem nic nie było w wierszu 1 kolumna 1 JSON. Zawsze dobrze jest sprawdzić, czy kod statusu żądania jest zgodny z oczekiwaniami.
thposs
0

Jeśli jesteś użytkownikiem systemu Windows, interfejs API Tweepy może wygenerować pustą linię między obiektami danych. Z powodu tej sytuacji może pojawić się błąd „JSONDecodeError: Oczekiwanie na wartość: wiersz 1 kolumna 1 (znak 0)”. Aby uniknąć tego błędu, możesz usunąć puste linie.

Na przykład:

 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

Odwołanie: API strumienia Twittera podaje JSONDecodeError („Oczekiwana wartość”, s, err.value) z None

drorhun
źródło
Nie sądzę, żeby puste linie stanowiły problem. Wyraźnie stwierdza, że ​​błąd dotyczy pierwszej linii w kolumnie 1. Myślę, że to obejście działa, ponieważ usuwa BOM z pliku. Możesz go szybko zweryfikować: 1. Sprawdź rozmiar oryginalnego pliku (kliknij prawym przyciskiem myszy> Właściwości), może to być 134,859 bajtów 2. Otwórz oryginalny plik za pomocą Notepad ++ 3. Zmień kodowanie z „UTF-8-BOM” na „ UTF-8 ”. Zapisz 4. Sprawdź ponownie rozmiar. Może to być 134,856 (3 bajty mniej)
Alex 75
0

Po prostu sprawdź, czy żądanie ma kod stanu 200. Na przykład:

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
źródło
0

Wystąpił taki błąd w odpowiedzi internetowego interfejsu API opartego na języku Python .text, ale doprowadził mnie tutaj, więc może to pomóc innym z podobnym problemem (bardzo trudno jest odfiltrować odpowiedzi i zażądać problemów podczas wyszukiwania przy użyciu requests..)

Użycie json.dumps()na argrze żądania data do utworzenia poprawnie zakończonego ciągu JSON przed testem POST naprawiło problem

requests.post(url, data=json.dumps(data))
ti7
źródło