Python / Json: esperando o nome da propriedade entre aspas duplas

106

Tenho tentado descobrir uma boa maneira de carregar objetos JSON em Python. Eu envio estes dados json:

{'http://example.org/about': {'http://purl.org/dc/terms/title': [{'type': 'literal', 'value': "Anna's Homepage"}]}}

para o back-end, onde será recebido como uma string que usei json.loads(data)para analisá-lo.

Mas cada vez eu recebia a mesma exceção:

ValueError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Pesquisei no Google, mas nada parece funcionar além desta solução json.loads(json.dumps(data))que pessoalmente me parece não muito eficiente já que aceita qualquer tipo de dados mesmo os que não estejam no formato json.

Qualquer sugestão será muito apreciado.

raeX
fonte
18
Meu erro não foi aspas duplas. Eu estava adicionando uma vírgula após o último par de valores-chave, como fazemos em python. Você não faz isso em JSON.
Luv33preet
4
sempre use em json.dumps()vez de apenas escrever python e esperar que a notação python funcione em seu leitor de JavaScript.
vy32
Tive esse problema porque peguei o resultado de a print(jsonpickle_deserialized_object_string)e tentei usar. Por algum motivo, print()muda as cotações de "para'
StingyJack
@ Luv33preet, obrigado, resolvi. mas estou esperando logger-msg como faltando vírgula ou algo assim, mas este erro não diz nada sobre isso,
ganeshdeshmukh

Respostas:

147

Este:

{'http://example.org/about': {'http://purl.org/dc/terms/title': [{'type': 'literal', 'value': "Anna's Homepage"}]}}

não é JSON.
Este:

{"http://example.org/about": {"http://purl.org/dc/terms/title": [{"type": "literal", "value": "Anna's Homepage"}]}}

é JSON.

EDIT:
Alguns comentaristas sugeriram que o acima não é suficiente.
Especificação JSON - RFC7159 afirma que uma string começa e termina com aspas. Isso é ".
O quoute único 'não tem significado semântico em JSON e é permitido apenas dentro de uma string.

ElmoVanKielmo
fonte
4
Obrigado :) Não prestei atenção nisso, estou usando o formato json correto ao enviar os dados, mas quando são recebidos no backend as aspas duplas são substituídas por simples! portanto, eu tenho essa exceção.
raeX de
23
esta não é uma solução. Uma solução diria a ele como modificar a string para json válido.
FistOfFury
2
@FistOfFury Sinto muito, mas sua declaração é baseada em uma falsa suposição de que uma string JSON inválida arbitrária pode ser transformada de forma confiável de forma programática em uma válida. Muitas respostas para esta pergunta tentam resolver o problema substituindo "por" e assim por diante. Devo dar exemplos simples de strings de entrada que quebrarão essas "soluções"? Aparentemente, o OP entendeu que o que estamos lidando não é JSON e conseguiu prosseguir - aceitou minha resposta. Dica - a string de entrada se parece mais com a saída do método Python dict .__ repr __ ().
ElmoVanKielmo
4
@ElmoVanKielmo não muda o fato de que sua resposta é uma afirmação, não uma resposta à pergunta. Você não fornece contexto ou explicação. As pessoas que vêm aqui em busca de informações sobre a questão ficarão desapontadas. Você pode ter ajudado a OP, mas outros nem tanto.
FistOfFury
43

como JSON permite apenas strings entre aspas duplas, você pode manipular a string assim:

str = str.replace("\'", "\"")

Isso substituirá todas as ocorrências de aspas simples por aspas duplas na string JSON str.

Você também pode usar o js-beautifyque é menos estrito:

$ pip install jsbeautifier
$ js-beautify file.js
elegível
fonte
3
Não é uma boa ideia porque pode substituir todos os por "s que está errado: EXEMPLO: 'é ruim' ->" é "ruim" -> string malformada
Reihan_amn
30

No meu caso, as aspas duplas não foram um problema.

A última vírgula me deu a mesma mensagem de erro.

{'a':{'b':c,}}
           ^

Para remover essa vírgula, escrevi um código simples.

import json

with open('a.json','r') as f:
    s = f.read()
    s = s.replace('\t','')
    s = s.replace('\n','')
    s = s.replace(',}','}')
    s = s.replace(',]',']')
    data = json.loads(s)

E isso funcionou para mim.

Greentec
fonte
4
+1 eu posso confirmar isso. A vírgula final produz essa mensagem de erro. Exemplo:, echo '{"json":"obj",}' | python -m json.tool quando executado no shell, fornece "Esperando nome da propriedade entre aspas duplas: linha 1 coluna 15 (caractere 14)". Vírgulas à direita não são JSON legais, mas seria bom se o módulo JSON do Python emitisse uma mensagem de erro relevante neste caso.
Laryx Decidua
7

Simplesmente, essa string não é um JSON válido. Como diz o erro, os documentos JSON precisam usar aspas duplas.

Você precisa corrigir a fonte dos dados.

Daniel Roseman
fonte
6

Eu verifiquei seus dados JSON

{'http://example.org/about': {'http://purl.org/dc/terms/title': [{'type': 'literal', 'value': "Anna's Homepage"}]}}

em http://jsonlint.com/ e os resultados foram:

Error: Parse error on line 1:
{   'http://example.org/
--^
Expecting 'STRING', '}', got 'undefined'

modificá-lo para a seguinte string resolve o erro JSON:

{
    "http://example.org/about": {
        "http://purl.org/dc/terms/title": [{
            "type": "literal",
            "value": "Anna's Homepage"
        }]
    }
}
Yaron
fonte
2
OBRIGADO POR ESSE LINK!
WolVes
6

As strings JSON devem usar aspas duplas. A biblioteca JSON python impõe isso para que você não consiga carregar sua string. Seus dados precisam ser assim:

{"http://example.org/about": {"http://purl.org/dc/terms/title": [{"type": "literal", "value": "Anna's Homepage"}]}}

Se isso não for algo que você pode fazer, você pode usar em ast.literal_eval()vez dejson.loads()

alexbclay
fonte
3
Isso não é uma restrição da biblioteca Python, mas do próprio formato JSON.
Daniel Roseman
Você está certo. No entanto, alguns analisadores JSON não impõem aspas duplas. Vou atualizar minha resposta.
alexbclay
desde que este não-JSON nunca tenha aspas duplas dentro de strings entre aspas simples, tudo o que você precisa fazer é substituir a string de todos os singles por duplos antes de invocar json.loads()
nigel222
2
Usar ast.literal_evalresultará em ValueError: malformed stringse a string JSON tiver um valor booleano.
Scratch'N'Purr
4
import ast

inpt = {'http://example.org/about': {'http://purl.org/dc/terms/title':
                                     [{'type': 'literal', 'value': "Anna's Homepage"}]}}

json_data = ast.literal_eval(json.dumps(inpt))

print(json_data)

Isto resolverá o problema.

balaji k
fonte
3

Como diz claramente um erro, os nomes devem ser colocados entre aspas duplas em vez de aspas simples. A string que você passa simplesmente não é um JSON válido. Deve ser parecido com

{"http://example.org/about": {"http://purl.org/dc/terms/title": [{"type": "literal", "value": "Anna's Homepage"}]}}
Pavel Gurkov
fonte
2

Usei esse método e consegui obter a saída desejada. meu script

x = "{'inner-temperature': 31.73, 'outer-temperature': 28.38, 'keys-value': 0}"

x = x.replace("'", '"')
j = json.loads(x)
print(j['keys-value'])

resultado

>>> 0
Hamed
fonte
2
with open('input.json','r') as f:
    s = f.read()
    s = s.replace('\'','\"')
    data = json.loads(s)

Isso funcionou perfeitamente bem para mim. Obrigado.

rohit9786
fonte
2
x = x.replace("'", '"')
j = json.loads(x)

Embora esta seja a solução correta, pode levar a uma grande dor de cabeça se houver um JSON como este -

{'status': 'success', 'data': {'equity': {'enabled': True, 'net': 66706.14510000008, 'available': {'adhoc_margin': 0, 'cash': 1277252.56, 'opening_balance': 1277252.56, 'live_balance': 66706.14510000008, 'collateral': 249823.93, 'intraday_payin': 15000}, 'utilised': {'debits': 1475370.3449, 'exposure': 607729.3129, 'm2m_realised': 0, 'm2m_unrealised': -9033, 'option_premium': 0, 'payout': 0, 'span': 858608.032, 'holding_sales': 0, 'turnover': 0, 'liquid_collateral': 0, 'stock_collateral': 249823.93}}, 'commodity': {'enabled': True, 'net': 0, 'available': {'adhoc_margin': 0, 'cash': 0, 'opening_balance': 0, 'live_balance': 0, 'collateral': 0, 'intraday_payin': 0}, 'utilised': {'debits': 0, 'exposure': 0, 'm2m_realised': 0, 'm2m_unrealised': 0, 'option_premium': 0, 'payout': 0, 'span': 0, 'holding_sales': 0, 'turnover': 0, 'liquid_collateral': 0, 'stock_collateral': 0}}}}

Reparou no valor "Verdadeiro" ? Use isto para fazer com que as coisas sejam verificadas novamente para Booleanos. Isso cobrirá esses casos -

x = x.replace("'", '"').replace("True", '"True"').replace("False", '"False"').replace("null", '"null"')
j = json.loads(x)

Além disso, certifique-se de não fazer

x = json.loads(x)

Tem que ser outra variável.

Amit Ghosh
fonte
1

Eu tive um problema semelhante. Dois componentes que se comunicavam entre si estavam usando uma fila.

O primeiro componente não estava executando json.dumps antes de colocar a mensagem na fila. Portanto, a string JSON gerada pelo componente de recebimento estava entre aspas simples. Isso estava causando um erro

 Expecting property name enclosed in double quotes

Adicionar json.dumps começou a criar JSON formatado corretamente e problema resolvido.

Rahul Bagal
fonte
1

Use o eval função.

Ele cuida da discrepância entre aspas simples e duplas.

msamogh
fonte
0

Como as outras respostas explicam bem, o erro ocorre por causa de caracteres de aspas inválidos passados ​​para o módulo json.

No meu caso, continuei a obter ValueError mesmo depois de substituir 'por "em minha string. O que finalmente percebi foi que alguns símbolos Unicode parecidos com aspas encontraram seu caminho na minha string:

           `  ´     

Para limpar tudo isso, você pode simplesmente passar sua string por meio de uma expressão regular:

import re

raw_string = '{“key”:“value”}'

parsed_string = re.sub(r"[“|”|‛|’|‘|`|´|″|′|']", '"', my_string)

json_object = json.loads(parsed_string)
Anders Solberg
fonte
-1

Já tive esse problema várias vezes quando o JSON foi editado manualmente. Se alguém deletar algo do arquivo sem perceber, pode ocorrer o mesmo erro.

Por exemplo, se seu último "}" JSON estiver faltando, ele gerará o mesmo erro.

Portanto, se você editar seu arquivo manualmente, certifique-se de formatá-lo como esperado pelo decodificador JSON, caso contrário, você terá o mesmo problema.

Espero que isto ajude!

Sneil
fonte
-2

É sempre ideal usar o json.dumps()método. Para me livrar desse erro, usei o seguinte código

json.dumps(YOUR_DICT_STRING).replace("'", '"')
Michael Elimu
fonte