JSON ValueError: Nombre de propiedad esperado: línea 1 columna 2 (carácter 1)

97

Tengo problemas para usar json.loads para convertir a un objeto dict y no puedo entender qué estoy haciendo mal. El error exacto que obtengo al ejecutar esto es

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

Aquí está mi código:

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)

Estoy bastante seguro de que el error se produce en la 2ª a la última línea.

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

pero no sé qué hacer para solucionarlo. Se agradecería cualquier consejo.

dredbound
fuente
3
¿Ves un error de sintaxis allí? Un "error, ¿es un error de copiar y pegar?
karthikr
¿Cuál fue la cadena JSON impresa por la línea print tweet.message.value?
Luke Woodward
1
Se ValueErrorenvía debido a un error en la entrada JSON, no a un problema en su código. (Además de los "que faltan, que normalmente deberían enviar un mensaje, SyntaxErrorasí que supongo que es solo un error de copiar y pegar)
Cld
(Por cierto, utf_8 es la codificación predeterminada para json.loads, por lo que no es necesario indicarlo).
Cld
Gracias por el aporte. Editada la pregunta, debería ser más clara ahora.
dredbound

Respuestas:

83

json.loadscargará una cadena json en una python dict, json.dumpsvolcará una python dicta una cadena json, por ejemplo:

>>> 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}'

Entonces esa línea es incorrecta ya que está intentando loaduna python dict, y json.loadsespera una válida json stringque debería tener <type 'str'>.

Entonces, si está tratando de cargar el json, debe cambiar lo que está cargando para que se vea como el json_stringanterior, o debería descargarlo. Esta es mi mejor suposición a partir de la información proporcionada. ¿Qué es lo que está tratando de lograr?

Además, no es necesario que especifique el uantes de sus cadenas, como @Cld mencionó en los comentarios.

Sí_yo_yo
fuente
2
json.loads cargará un -> objeto json <- en un dict de Python - Eso es contrario a lo que dicen los documentos e incluso a lo que hace su propio código - está usando cargas () en una cadena, no un json objeto .
7stud
Sí @ 7stud, tienes razón, está cargando una cadena. Pero debe ser una cadena json válida. Actualicé mi respuesta.
Yep_It's_Me
186

Encontré otro problema que devuelve el mismo error.

Emisión de comillas simples

Usé una cadena json con comillas simples :

{
    'property': 1
}

Pero json.loadssolo acepta comillas dobles para las propiedades json :

{
    "property": 1
}

Problema de coma final

json.loads no acepta una coma final:

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

Solución: astpara resolver problemas de comillas simples y comas finales

Puede usar ast(parte de la biblioteca estándar para Python 2 y 3) para este procesamiento. Aquí hay un ejemplo :

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"}

El uso astevitará que tenga problemas de comillas simples y comas finales al interpretar JSON como el diccionario de Python (por lo que debe seguir la sintaxis del diccionario de Python). Es una alternativa de eval()función bastante buena y segura para estructuras literales.

La documentación de Python nos advirtió sobre el uso de cadenas grandes / complejas:

Advertencia Es posible bloquear el intérprete de Python con una cadena suficientemente grande / compleja debido a las limitaciones de profundidad de la pila en el compilador AST de Python.

json.dumps con comillas simples

Para usar json.dumpscon comillas simples fácilmente, puede usar este código:

import ast
import json

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

ast documentación

ast Python 3 doc

ast Python 2 doc

Herramienta

Si edita JSON con frecuencia, puede usar CodeBeautify . Le ayuda a corregir el error de sintaxis y a minimizar / embellecer JSON.

Espero que ayude.

Samuel Dauzon
fuente
10
  1. reemplazar todas las comillas simples con comillas dobles
  2. reemplace 'u "' de sus cadenas a '"' ... así que básicamente convierta unicodes internos en cadenas antes de cargar la cadena en json
>> strs = "{u'key':u'val'}"
>> strs = strs.replace("'",'"')
>> json.loads(strs.replace('u"','"'))
Vinay Pande
fuente
1
una forma más pitónica sería usar ast.literal_eval ("{u'key ': u'val'}"). Se ocupará de todos los problemas relacionados con el formato
Vinay Pande
json.loads (strs.replace ('u "', '')) no funciona. Aquí está el siguiente error, Traceback (última llamada más reciente): Archivo" <stdin> ", línea 1, en <module> Archivo "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", línea 338, en las cargas return _default_decoder.decode (s) obj, end = self.scan_once (s , idx) ValueError: Esperando nombre de propiedad: línea 1 columna 2 (carácter 1)
Sanjay Pradeep
4

Todas las demás respuestas pueden responder a su consulta, pero enfrenté el mismo problema que se debió a un desvío ,que agregué al final de mi cadena json de esta manera:

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

Finalmente lo hice funcionar cuando eliminé extra ,como este:

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

¡Espero que esto ayude! salud.

Rishabh Agrahari
fuente
1
bueno, aunque esto ya está cubierto por la respuesta de
jedema
@fedorqui Esa parte se agregó después de mi respuesta ( stackoverflow.com/posts/36599122/revisions ) Ahora, es posible que desee dar un +1 :)
Rishabh Agrahari
1
oh, tienes razón! Fue agregado en enero de 2018. Disculpas y +1 :)
fedorqui 'ASÍ que deja de dañar'
0

usado ast, ejemplo

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
fuente
0

Un caso diferente en el que encontré esto fue cuando estaba usando echopara canalizar el JSON en mi script de Python y envolví descuidadamente la cadena JSON entre comillas dobles:

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

Tenga en cuenta que la cadena JSON en sí tiene comillas y debería haberlo hecho:

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

Así las cosas, esto es lo que recibió el script en Python: {thumbnailWidth: 640}; las comillas dobles se eliminaron efectivamente.

Jim Hoagland
fuente