JSON ValueError: Nom de la propriété attendue: ligne 1 colonne 2 (car 1)

97

J'ai du mal à utiliser json.loads pour convertir en un objet dict et je ne peux pas comprendre ce que je fais mal.

ValueError: Expecting property name: line 1 column 2 (char 1)

Voici mon code:

from kafka.client import KafkaClient
from kafka.consumer import SimpleConsumer
from kafka.producer import SimpleProducer, KeyedProducer
import pymongo
from pymongo import MongoClient
import json

c = MongoClient("54.210.157.57")
db = c.test_database3
collection = db.tweet_col

kafka = KafkaClient("54.210.157.57:9092")

consumer = SimpleConsumer(kafka,"myconsumer","test")
for tweet in consumer:
    print tweet.message.value
    jsonTweet=json.loads(({u'favorited': False, u'contributors': None})
    collection.insert(jsonTweet)

Je suis presque sûr que l'erreur se produit entre la deuxième et la dernière ligne

jsonTweet=json.loads({u'favorited': False, u'contributors': None})

mais je ne sais pas quoi faire pour y remédier. Tout avis sera le bienvenu.

dredbound
la source
3
voyez-vous une erreur de syntaxe? Une "erreur est-ce une erreur de copier-coller?
karthikr
Quelle était la chaîne JSON imprimée par la ligne print tweet.message.value?
Luke Woodward
1
Le ValueErrorest envoyé en raison d'une erreur dans l'entrée JSON, pas d'un problème dans votre code. (À côté des disparus "qui devraient normalement envoyer un SyntaxError, je suppose que c'est juste une erreur de copier-coller.)
Cld
(À propos, utf_8 est l'encodage par défaut pour json.loads, il n'est donc pas nécessaire de l'indiquer.)
Cld
Merci pour la contribution. Modifié la question, devrait être plus clair maintenant.
dredbound le

Réponses:

84

json.loadschargera une chaîne json dans un python dict, json.dumpsvidera un python dictdans une chaîne json, par exemple:

>>> json_string = '{"favorited": false, "contributors": null}'
'{"favorited": false, "contributors": null}'
>>> value = json.loads(json_string)
{u'favorited': False, u'contributors': None}
>>> json_dump = json.dumps(value)
'{"favorited": false, "contributors": null}'

Donc, cette ligne est incorrecte puisque vous essayez loadun python dict, et json.loadsattendez un valide json stringqui devrait avoir <type 'str'>.

Donc, si vous essayez de charger le json, vous devez changer ce que vous chargez pour qu'il ressemble à ce qui json_stringprécède, ou vous devriez le vider. C'est juste ma meilleure estimation à partir des informations fournies. Qu'est-ce que vous essayez d'accomplir?

De plus, vous n'avez pas besoin de spécifier le uavant vos chaînes, comme @Cld l'a mentionné dans les commentaires.

Yep_It's_Me
la source
2
json.loads chargera un -> objet json <- dans un dict python - C'est contraire à ce que la documentation dit et même à ce que fait votre propre code - vous utilisez load () sur une chaîne, pas un json objet .
7
Oui @ 7stud, vous avez raison, il charge une chaîne. Mais ce doit être une chaîne json valide. J'ai mis à jour ma réponse.
Yep_It's_Me
187

J'ai rencontré un autre problème qui renvoie la même erreur.

Problème de devis unique

J'ai utilisé une chaîne json avec des guillemets simples :

{
    'property': 1
}

Mais json.loadsn'accepte que les guillemets doubles pour les propriétés json :

{
    "property": 1
}

Dernier problème de virgule

json.loads n'accepte pas une virgule finale:

{
  "property": "text", 
  "property2": "text2",
}

Solution: astpour résoudre les problèmes de guillemets simples et de virgules finales

Vous pouvez utiliser ast(une partie de la bibliothèque standard pour Python 2 et 3) pour ce traitement. Voici un exemple :

import ast
# ast.literal_eval() return a dict object, we must use json.dumps to get JSON string
import json

# Single quote to double with ast.literal_eval()
json_data = "{'property': 'text'}"
json_data = ast.literal_eval(json_data)
print(json.dumps(json_data))
# Displays : {"property": "text"}

# ast.literal_eval() with double quotes
json_data = '{"property": "text"}'
json_data = ast.literal_eval(json_data)
print(json.dumps(json_data))
# Displays : {"property": "text"}

# ast.literal_eval() with final coma
json_data = "{'property': 'text', 'property2': 'text2',}"
json_data = ast.literal_eval(json_data)
print(json.dumps(json_data))
# Displays : {"property2": "text2", "property": "text"}

L'utilisation astvous évitera les problèmes de guillemets simples et de virgules finales en interprétant le dictionnaire JSON comme Python (vous devez donc suivre la syntaxe du dictionnaire Python). C'est une alternative de eval()fonction assez bonne et sûre pour les structures littérales.

La documentation Python nous a avertis de l'utilisation d'une chaîne volumineuse / complexe:

Avertissement Il est possible de planter l'interpréteur Python avec une chaîne suffisamment grande / complexe en raison des limitations de profondeur de pile dans le compilateur AST de Python.

json.dumps avec des guillemets simples

Pour utiliser json.dumpsfacilement les guillemets simples, vous pouvez utiliser ce code:

import ast
import json

data = json.dumps(ast.literal_eval(json_data_single_quote))

ast Documentation

ast Python 3 doc

ast Python 2 doc

Outil

Si vous modifiez fréquemment JSON, vous pouvez utiliser CodeBeautify . Il vous aide à corriger les erreurs de syntaxe et à minimiser / embellir JSON.

J'espère que cela aide.

Samuel Dauzon
la source
10
  1. remplacer tous les guillemets simples par des guillemets doubles
  2. remplacez 'u "' de vos chaînes par '"' ... donc convertissez essentiellement les unicodes internes en chaînes avant de charger la chaîne dans json
>> strs = "{u'key':u'val'}"
>> strs = strs.replace("'",'"')
>> json.loads(strs.replace('u"','"'))
Vinay Pande
la source
1
une manière plus pythonique serait d'utiliser ast.literal_eval ("{u'key ': u'val'}"). Il s'occupera de tous les problèmes liés au format
Vinay Pande
json.loads (strs.replace ('u "', '')) ne fonctionne pas. Voici l'erreur ci-dessous, Traceback (dernier appel en dernier): Fichier" <stdin> ", ligne 1, dans <module> Fichier "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", ligne 338, dans les charges, renvoie _default_decoder.decode (s) obj, end = self.scan_once (s , idx) ValueError: Nom de la propriété attendue: ligne 1 colonne 2 (car 1)
Sanjay Pradeep
4

Toutes les autres réponses peuvent répondre à votre requête, mais j'ai rencontré le même problème qui était dû à un écart ,que j'ai ajouté à la fin de ma chaîne json comme ceci:

{
 "key":"123sdf",
 "bus_number":"asd234sdf",
}

Je l'ai finalement fait fonctionner lorsque j'ai supprimé un supplément , comme celui-ci:

{
 "key":"123sdf",
 "bus_number":"asd234sdf"
}

J'espère que cette aide! à votre santé.

Rishabh Agrahari
la source
1
bon, bien que cela soit déjà couvert par la réponse de
jedema
@fedorqui Cette partie a été ajoutée après ma réponse ( stackoverflow.com/posts/36599122/revisions ) Maintenant, vous voudrez peut-être donner un +1 :)
Rishabh Agrahari
1
oh, tu as raison! Il a été ajouté par Jan 2018. Excuses et +1 :)
fedorqui 'SO stop nuire'
0

utilisé ast, exemple

In [15]: a = "[{'start_city': '1', 'end_city': 'aaa', 'number': 1},\
...:      {'start_city': '2', 'end_city': 'bbb', 'number': 1},\
...:      {'start_city': '3', 'end_city': 'ccc', 'number': 1}]"
In [16]: import ast
In [17]: ast.literal_eval(a)
Out[17]:
[{'end_city': 'aaa', 'number': 1, 'start_city': '1'},
 {'end_city': 'bbb', 'number': 1, 'start_city': '2'},
 {'end_city': 'ccc', 'number': 1, 'start_city': '3'}]
xin.chen
la source
0

Un cas différent dans lequel j'ai rencontré cela était lorsque j'utilisais echopour diriger le JSON dans mon script python et que j'enveloppais négligemment la chaîne JSON entre guillemets:

echo "{"thumbnailWidth": 640}" | myscript.py

Notez que la chaîne JSON elle-même a des guillemets et j'aurais dû faire:

echo '{"thumbnailWidth": 640}' | myscript.py

En fait, voici ce que le script python a reçu {thumbnailWidth: 640}:; les guillemets doubles ont été effectivement supprimés.

Jim Hoagland
la source