JSON ValueError: Esperando nome da propriedade: linha 1 coluna 2 (caractere 1)

97

Estou tendo problemas para usar json.loads para converter em um objeto dict e não consigo descobrir o que estou fazendo de errado. O erro exato que recebo ao executar isso é

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

Aqui está o meu 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)

Tenho quase certeza de que o erro está ocorrendo da 2ª à última linha

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

mas não sei o que fazer para consertar. Qualquer conselho seria apreciado.

dredbound
fonte
3
você vê um erro de sintaxe aí? Um vadio "é que uma cópia colar de erro?
karthikr
Qual foi a string JSON impressa pela linha print tweet.message.value?
Luke Woodward
1
O ValueErroré enviado devido a um erro na entrada JSON, não é um problema em seu código. (Além da falta de "quem normalmente deveria enviar um, SyntaxErrorentão presumo que seja apenas um erro de copiar e colar.)
Cld
(A propósito, utf_8 é a codificação padrão para json.loads, portanto, não é necessário indicá-lo.)
Cld
Obrigado pela contribuição. Editou a pergunta, deve ficar mais clara agora.
dragado em

Respostas:

83

json.loadsirá carregar uma string json em um python dict, json.dumpsirá despejar um python dictem uma string json, por exemplo:

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

Portanto, essa linha está incorreta, pois você está tentando loadum python dicte json.loadsestá esperando um válido json stringque deveria ter <type 'str'>.

Portanto, se você está tentando carregar o json, deve alterar o que está carregando para se parecer com o json_stringacima, ou deve descartá-lo. Este é apenas meu melhor palpite com base nas informações fornecidas. O que você está tentando realizar?

Além disso, você não precisa especificar o uantes de suas strings, como @Cld mencionou nos comentários.

Sim_é_é
fonte
2
json.loads carregará um -> objeto json <- em um dicionário python - Isso é contrário ao que dizem os documentos e até mesmo o que seu próprio código faz - você está usando load () em uma string, não em um json objeto .
7 de
Sim @ 7stud, você está correto, ele está carregando uma string. Mas deve ser uma string json válida. Eu atualizei minha resposta.
Yep_It's_Me
186

Encontrei outro problema que retorna o mesmo erro.

Problema de aspas simples

Usei uma string json com aspas simples :

{
    'property': 1
}

Mas json.loadsaceita apenas aspas duplas para propriedades json :

{
    "property": 1
}

Problema de vírgula final

json.loads não aceita uma vírgula final:

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

Solução: astpara resolver problemas de aspas simples e vírgula final

Você pode usar ast(parte da biblioteca padrão para Python 2 e 3) para este processamento. Aqui está um exemplo :

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

O uso astimpedirá você de problemas de aspas simples e vírgulas finais ao interpretar o dicionário JSON como o Python (portanto, você deve seguir a sintaxe do dicionário Python). É uma alternativa de eval()função muito boa e segura para estruturas literais.

A documentação do Python nos alertou sobre o uso de strings grandes / complexas:

Aviso É possível travar o interpretador Python com uma string suficientemente grande / complexa devido às limitações de profundidade da pilha no compilador AST do Python.

json.dumps com aspas simples

Para usar json.dumpsaspas simples facilmente, você pode usar este código:

import ast
import json

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

ast documentação

ast Python 3 doc

ast Python 2 doc

Ferramenta

Se você edita JSON com frequência, pode usar CodeBeautify . Isso ajuda a corrigir erros de sintaxe e reduzir / embelezar JSON.

Espero que ajude.

Samuel Dauzon
fonte
10
  1. substitua todas as aspas simples por aspas duplas
  2. substitua 'u "' de suas strings por '"' ... então converta basicamente unicodes internos em strings antes de carregar a string em json
>> strs = "{u'key':u'val'}"
>> strs = strs.replace("'",'"')
>> json.loads(strs.replace('u"','"'))
Vinay pande
fonte
1
a maneira mais pythônica seria usar ast.literal_eval ("{u'key ': u'val'}"). Ele cuidará de todos os problemas relacionados ao formato
Vinay Pande
json.loads (strs.replace ('u "', '')) não está funcionando. Aqui está o erro abaixo, Traceback (última chamada mais recente): Arquivo" <stdin> ", linha 1, no arquivo <module> "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", linha 338, nas cargas return _default_decoder.decode (s) obj, end = self.scan_once (s , idx) ValueError: Esperando nome da propriedade: linha 1 coluna 2 (caractere 1)
Sanjay Pradeep
4

Todas as outras respostas podem responder à sua pergunta, mas eu enfrentei o mesmo problema devido ao extravio ,que adicionei no final da minha string json desta forma:

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

Eu finalmente consegui fazer funcionar quando removi itens extras ,como este:

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

Espero que esta ajuda! Felicidades.

Rishabh Agrahari
fonte
1
boa, embora isso já esteja coberto pela resposta de
jedema
@fedorqui Essa parte foi adicionada após minha resposta ( stackoverflow.com/posts/36599122/revisions ) Agora, você pode dar um +1 :)
Rishabh Agrahari
1
oh, você está certo! Foi adicionado em janeiro de 2018. Desculpas e +1 :)
fedorqui 'SO pare de prejudicar'
0

usado ast, exemplo

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

Um caso diferente em que encontrei isso foi quando estava usando echopara canalizar o JSON em meu script Python e descuidadamente envolvi a string JSON entre aspas duplas:

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

Observe que a própria string JSON tem aspas e eu deveria ter feito:

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

Do jeito que estava, isto é o que o script python recebeu {thumbnailWidth: 640}:; as aspas duplas foram efetivamente eliminadas.

Jim Hoagland
fonte