JSONDecodeError: Valeur attendue: ligne 1 colonne 1 (caractère 0)

260

Je reçois une erreur Expecting value: line 1 column 1 (char 0)en essayant de décoder JSON.

L'URL que j'utilise pour l'appel d'API fonctionne bien dans le navigateur, mais donne cette erreur lorsqu'elle est effectuée via une demande de boucle. Voici le code que j'utilise pour la demande curl.

L'erreur se produit à 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

Traceback complet:

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)
user1328021
la source
2
Dernier point mais non le moindre, qu'est-ce qui print repr(response_json)vous dit que vous êtes passé .loads()?
Martijn Pieters
4
Un de plus: pourquoi utiliser simplejsonquand vous pouvez simplement utiliser le stdlib json(qui est la même bibliothèque quesimplejson )?
Martijn Pieters
3
C'est une chaîne vide. Votre web_fetch() appel a échoué.
Martijn Pieters
1
Oui, je vous recommande d'utiliser quelque chose de plus facile à utiliser que pycurl. requestsoffre une API beaucoup plus facile, surtout quand il s'agit de déboguer ce qui se passe. Sauf si vous devez spécifiquement avoir une version plus récente de la simplejsonbibliothèque, restez avec json, vous évite une dépendance à gérer.
Martijn Pieters
1
est response_jsonla valeur de retour de .json()? Vous disposez alors déjà de données décodées et vous n'avez plus besoin de les utiliser json.loads(). responsel'a décodé pour vous.
Martijn Pieters

Réponses:

125

Pour résumer la conversation dans les commentaires:

  • Il n'est pas nécessaire d'utiliser la simplejsonbibliothèque, la même bibliothèque est incluse avec Python que le jsonmodule.

  • Il n'est pas nécessaire de décoder une réponse de UTF8 en unicode, la méthode simplejson/ json .loads()peut gérer les données codées UTF8 en mode natif.

  • pycurla une API très archaïque. Sauf si vous avez une exigence spécifique pour l'utiliser, il existe de meilleurs choix.

requestsoffre l'API la plus conviviale, y compris le support JSON. Si vous le pouvez, remplacez votre appel par:

import requests

return requests.get(url).json()
Martijn Pieters
la source
93
J'obtiens cette même erreur en utilisant requests! La trace semble suggérer que les requestsutilisations complexjson, les utilisations simplejson. Bizarre.
rayu
@Rayu: les demandes seront utiliséessimplejson si disponibles; certaines personnes souhaitent utiliser la dernière version de simplejson plutôt que celle fournie avec le stdlib Python.
Martijn Pieters
5
"Il n'est pas nécessaire d'utiliser la bibliothèque simplejson, la même bibliothèque est incluse avec Python que le module json." ... Je ne suis respectueusement pas d'accord. simplejsonutilise le intégré jsonsous le capot, mais donne plus d'erreurs descriptives. Dans ce cas, l'utilisation jsonvous donnerait simplement un générique ValueError: No JSON object could be decoded.
BoltzmannBrain
2
Cela pourrait-il être causé par un abandon ou un json incomplet? Je l'obtiens au hasard de temps en temps, je ne sais pas comment le reproduire.
Christophe Roussy
2
@ChristopheRoussy: oui, c'est plutôt le point de la question (le PO a obtenu une réponse vide u'' ). Votre JSONDecodeErrorvous indique que beaucoup de données ont été analysées avec succès avant de rencontrer une erreur; cela peut être dû au fait qu'il existe des données non valides à ce stade (document JSON mal formé ou corrompu) ou parce que les données ont été tronquées.
Martijn Pieters
64

Vérifiez le corps de données de la réponse, si des données réelles sont présentes et si un vidage de données semble être bien formaté.

Dans la plupart des cas, votre json.loads- JSONDecodeError: Expecting value: line 1 column 1 (char 0)erreur est due à:

  • citation non conforme JSON
  • Sortie XML / HTML (c'est-à-dire une chaîne commençant par <), ou
  • encodage de caractères incompatibles

En fin de compte, l'erreur vous indique qu'à la toute première position, la chaîne n'est déjà pas conforme à JSON.

En tant que tel, si l'analyse échoue malgré un corps de données qui ressemble à JSON à première vue, essayez de remplacer les guillemets du corps de données:

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

Remarque: les citations dans les données doivent être correctement échappées

Lorenz Lo Sauer
la source
4
Dans les commentaires, il est clair que le PO a obtenu une réponse vide. Depuis requests.get(url).json()Just Works, le JSON n'est pas mal formé non plus.
Martijn Pieters
JSONDecodeError: Expecting value: line 1 column 1 (char 0)se produit spécifiquement lorsqu'une chaîne vide est passée au décodage json
wesinat0r
JSONDecodeError: Expecting value: line 1 column 1 (char 0)se produit également lorsque la première ligne de la réponse json n'est pas valide. Exemple réponse de l' exécution d' une az clicommande est ["WARNING: The default kind for created storage account will change to 'StorageV2' from 'Storage' in the future", '{',. Cela m'a donné l'erreur qui m'a conduit ici. Le reste de la réponse EST un objet json valide. Juste cette première ligne casse les choses.
SeaDude
35

Avec la requestslib JSONDecodeErrorpeut arriver quand vous avez un code d'erreur http comme 404 et essayez d'analyser la réponse en JSON!

Vous devez d'abord vérifier 200 (OK) ou le laisser augmenter en cas d'erreur pour éviter ce cas. Je souhaite qu'il échoue avec un message d'erreur moins cryptique.

REMARQUE : comme Martijn Pieters l'a indiqué dans les commentaires, les serveurs peuvent répondre avec JSON en cas d'erreur (cela dépend de l'implémentation), donc la vérification de l'en- Content-Typetête est plus fiable.

Christophe Roussy
la source
Désolé pour l'ancien commentaire, mais pourriez-vous créer un lien vers un exemple? J'essaie de faire passer mes compétences de "réaliser une action" à "tenter de réaliser une action, renvoyer une réponse, réagir en conséquence".
dcclassics
@dcclassics: Exemple: il échoue côté serveur et le serveur répond en affichant une page d'erreur (HTML) au lieu de répondre avec JSON, donc le code analysant la réponse tentera de lire JSON mais échouera sur les balises HTML.
Christophe Roussy
1
Les serveurs peuvent et incluent des corps JSON dans les réponses d'erreur. Ce ne sont pas seulement 200 réponses OK. Vous souhaitez vérifier l'en-tête Content-Type.
Martijn Pieters
29

Je pense que cela vaut la peine de mentionner que dans les cas où vous analysez le contenu d'un fichier JSON lui-même - des vérifications d'intégrité peuvent être utiles pour vous assurer que vous invoquez réellement json.loads()le contenu du fichier, par opposition au chemin du fichier de ce JSON :

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

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

Je suis un peu gêné d'admettre que cela peut arriver parfois:

contents = json.loads(json_file_path)
alex
la source
Eh bien .. Cela arrive parfois. Merci Ça a fonctionné btw.
Sachin Kumar
Je pense que dans ce cas, on devrait utiliser à la json.load()place.
Coddy
13

Vérifiez le format d'encodage de votre fichier et utilisez le format d'encodage correspondant lors de la lecture du fichier. Cela résoudra votre problème.

with open("AB.json", encoding='utf-8', errors='ignore') as json_data:
     data = json.load(json_data, strict=False)
Ramineni Ravi Teja
la source
3
Cela a fonctionné pour moi avec le petit changement de encoding='utf-8', donc je suppose que parfois vous devez essayer quelques choses.
RobertMyles
9

Souvent, ce sera parce que la chaîne que vous essayez d'analyser est vide:

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

Vous pouvez y remédier en vérifiant s'il json_stringest vide au préalable:

import json

if json_string:
    x = json.loads(json_string)
else:
    // Your logic here
    x = {}
Alex W
la source
Pendant le débogage plus haut dans mon code, j'appelais response.read(), puis j'ai été consterné lorsqu'un autre appel a abouti, Expecting value: line 1etc. Suppression de l'instruction de débogage et problème résolu.
Joe
Pour déboguer, vous pouvez également utiliser ce joli site Web jsonlint.com
Roelant
4

Il peut y avoir des 0 intégrés, même après avoir appelé decode (). Utilisez 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
la source
2

J'ai eu exactement ce problème en utilisant des demandes. Merci à Christophe Roussy pour son explication.

Pour déboguer, j'ai utilisé:

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

Je recevais une réponse 404 de l'API.

Kelsie Braidwood
la source
1
Il peut être simplifié en response.status_codeou print(response.status_code).
TitanFighter
1

J'avais le même problème avec les requêtes (la bibliothèque python). C'était justement l'en- accept-encodingtête.

C'était réglé de cette façon: 'accept-encoding': 'gzip, deflate, br'

Je l'ai simplement supprimé de la demande et j'ai cessé de recevoir l'erreur.

Seu Madruga
la source
1

Pour moi, il n'utilisait pas d'authentification dans la demande.

Neel0507
la source
1

Pour moi, le serveur répondait par autre chose que 200 et la réponse n'était pas au format json. J'ai fini par le faire avant l'analyse 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
la source
C'était le problème pour moi. Le code d'état était 500 (erreur interne du serveur) au lieu de 200, donc aucun json n'a été retourné et donc il n'y avait rien dans la ligne 1 col 1 du json. Toujours bon de vérifier que le code d'état de la demande correspond à ce que vous attendez.
thposs
1

J'ai rencontré le même problème, lors de l'impression de la chaîne json ouverte à partir d'un fichier json, j'ai trouvé que la chaîne json commençait par 'ï »¿', ce qui, en faisant une certaine recherche, est dû au fait que le fichier est par défaut décodé avec UTF-8, et en changeant l'encodage en utf-8-sig, la marque est supprimée et charge json sans problème:

open('test.json', encoding='utf-8-sig')
user9571515
la source
0

Si vous êtes un utilisateur Windows, l'API Tweepy peut générer une ligne vide entre les objets de données. En raison de cette situation, vous pouvez obtenir l'erreur "JSONDecodeError: valeur attendue: ligne 1 colonne 1 (caractère 0)". Pour éviter cette erreur, vous pouvez supprimer des lignes vides.

Par exemple:

 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

Référence: L' API de flux Twitter donne JSONDecodeError ("Valeur attendue", s, valeur err.) de None

drorhun
la source
Je ne pense pas que les lignes vides soient un problème. Il indique clairement que l'erreur se trouve sur la colonne 1 de la ligne 1. Je pense que cette solution de contournement fonctionne car elle supprime la nomenclature du fichier. Vous pouvez le vérifier rapidement: 1. Vérifiez la taille de votre fichier d'origine (clic droit> Propriétés), il peut être de 134,859 octets 2. Ouvrez le fichier d'origine avec Notepad ++ 3. Changez l'encodage de "UTF-8-BOM" en " UTF-8 ". Enregistrer 4. Vérifiez à nouveau la taille. Ca peut être 134.856 (3 octets de moins)
Alex 75
0

Vérifiez simplement si la demande a un code d'état 200. Ainsi, par exemple:

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
la source
0

J'ai reçu une telle erreur dans la réponse d'une API Web basée sur Python .text, mais cela m'a conduit ici, donc cela peut aider les autres avec un problème similaire (il est très difficile de filtrer la réponse et de demander des problèmes dans une recherche lors de l'utilisation de requests..)

L'utilisation json.dumps()de l' argument de demande data pour créer une chaîne JSON correctement échappée avant le POSTing a résolu le problème pour moi

requests.post(url, data=json.dumps(data))
ti7
la source