Python / Json: nombre de propiedad esperado entre comillas dobles

110

He estado tratando de encontrar una buena manera de cargar objetos JSON en Python. Envío estos datos json:

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

al backend donde se recibirá como una cadena, luego solía json.loads(data)analizarlo.

Pero cada vez tengo la misma excepción:

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

Lo busqué en Google, pero nada parece funcionar además de esta solución, json.loads(json.dumps(data))que personalmente no me parece tan eficiente ya que acepta cualquier tipo de datos, incluso los que no están en formato json.

Cualquier sugerencia será muy apreciada.

raeX
fuente
18
Mi error no fueron las comillas dobles. Estaba agregando una coma después del último par clave-valor como lo hacemos en Python. No haces eso en JSON.
Luv33preet
4
use siempre enjson.dumps() lugar de simplemente escribir python y esperar que la notación python funcione en su lector de JavaScript.
vy32
Tuve este problema porque tomé el resultado de a print(jsonpickle_deserialized_object_string)e intenté usarlo. Por alguna razón print()cambia las citas de "a'
StingyJack
@ Luv33preet, gracias, lo resolví. pero espero logger-msg como falta-coma o algo así, pero este error no dice nada al respecto,
ganeshdeshmukh
consulte stackoverflow.com/a/63862387/1497139 para una solución rápida
Wolfgang Fahl hace

Respuestas:

150

Esta:

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

no es JSON.
Esta:

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

es JSON.

EDITAR:
Algunos comentaristas sugirieron que lo anterior no es suficiente.
Especificación JSON: RFC7159 establece que una cadena comienza y termina con comillas. Eso es ".
Single Quoute 'no tiene significado semántico en JSON y solo se permite dentro de una cadena.

ElmoVanKielmo
fuente
4
Gracias :) No presté atención a eso, estoy usando el formato json correcto al enviar los datos, pero cuando se reciben en el backend, ¡las comillas dobles se reemplazan por simples! por lo tanto obtuve esa excepción.
raeX
25
Esta no es una solución. Una solución le diría cómo modificar la cadena a json válido.
FistOfFury
2
@FistOfFury Lo siento, pero su declaración se basa en una suposición falsa de que una cadena JSON inválida arbitraria puede convertirse de manera confiable mediante programación en una válida. Muchas respuestas para esta pregunta tratan de abordar el problema reemplazando "con" y así sucesivamente. ¿Tengo que darles ejemplos simples de cadenas de entrada que romperán estas "soluciones"? Aparentemente, OP entendió que lo que estamos tratando no es JSON y pude continuar, acepté mi respuesta. Sugerencia: la cadena de entrada se parece más a la salida del método Python dict .__ repr __ ().
ElmoVanKielmo
4
@ElmoVanKielmo no cambia el hecho de que tu respuesta es una declaración, no una respuesta a la pregunta. No proporciona contexto ni explicación. Las personas que vengan aquí en busca de información sobre la pregunta se sentirán decepcionadas. Puede que hayas ayudado a OP, pero a otros no tanto.
FistOfFury
Una declaración simple y clara a menudo ayuda mucho. Especialmente, cuando hay muchas otras respuestas alrededor.
Ben
47

como JSON solo permite encerrar cadenas con comillas dobles, puede manipular la cadena de esta manera:

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

si su JSON contiene comillas simples ( \'), entonces debe usar el siguiente código más preciso:

import re
p = re.compile('(?<!\\\\)\'')
str = p.sub('\"', str)

Esto reemplazará todas las ocurrencias de comillas simples con comillas dobles en la cadena JSON stry, en el último caso, no reemplazará las comillas simples escapadas.

También puede usar lo js-beautifyque es menos estricto:

$ pip install jsbeautifier
$ js-beautify file.js
elig
fuente
4
No es una buena idea porque puede reemplazar todas las "por", lo cual es incorrecto: EJEMPLO: 'es malo' -> "es malo" -> cadena con formato incorrecto
Reihan_amn
@Reihan_amn He agregado una alternativa de expresión regular más precisa para los casos en los que se utilizan comillas simples de escape.
eligió el
la expresión regular da un error de sintaxis
Wolfgang Fahl
@WolfgangFahl, puede intentarlo de nuevo ahora.
elig hace
gracias, estoy usando stackoverflow.com/a/63862387/1497139 en su lugar ahora
Wolfgang Fahl hace
33

En mi caso, las comillas dobles no fueron un problema.

La última coma me dio el mismo mensaje de error.

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

Para eliminar esta coma, escribí un código simple.

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)

Y esto funcionó para mí.

greentec
fuente
4
+1 Puedo confirmar esto. La coma al final produce este mensaje de error. Ejemplo:, echo '{"json":"obj",}' | python -m json.tool cuando se ejecuta en el shell, da "Esperando nombre de propiedad entre comillas dobles: línea 1 columna 15 (carácter 14)". Las comas finales no son JSON legales, pero sería bueno si el módulo JSON de Python emitiera un mensaje de error relevante en este caso.
Laryx Decidua
7

Simplemente, esa cadena no es JSON válido. Como dice el error, los documentos JSON deben usar comillas dobles.

Necesita arreglar la fuente de los datos.

Daniel Roseman
fuente
6

Revisé tus datos JSON

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

en http://jsonlint.com/ y los resultados fueron:

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

modificarlo a la siguiente cadena resuelve el error JSON:

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

Las cadenas JSON deben utilizar comillas dobles. La biblioteca JSON python hace cumplir esto, por lo que no puede cargar su cadena. Sus datos deben verse así:

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

Si eso no es algo que pueda hacer, podría usar en ast.literal_eval()lugar dejson.loads()

alexbclay
fuente
3
Esa no es una restricción de la biblioteca de Python, sino del formato JSON en sí.
Daniel Roseman
Estás en lo correcto. Sin embargo, algunos analizadores JSON no aplican las comillas dobles. Actualizaré mi respuesta.
alexbclay
siempre que este no JSON nunca tenga comillas dobles dentro de cadenas de comillas simples, todo lo que tiene que hacer es sustituir todas las cadenas por dobles antes de invocarjson.loads()
nigel222
2
El uso ast.literal_evaldará como resultado ValueError: malformed stringsi la cadena JSON tiene un 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)

Esto solucionará el problema.

balaji k
fuente
3

Como dice claramente por error, los nombres deben escribirse entre comillas dobles en lugar de comillas simples. La cadena que pasa no es un JSON válido. Debería verse como

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

Usé este método y logré obtener el resultado deseado. mi guion

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

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

salida

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

Esto funcionó perfectamente bien para mí. Gracias.

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

Aunque esta es la solución correcta, puede provocar un gran dolor de cabeza si hay un 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}}}}

¿Notó ese valor "Verdadero" ? Use esto para hacer que las cosas se verifiquen dos veces para los booleanos. Esto cubrirá esos casos:

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

Además, asegúrese de no hacer

x = json.loads(x)

Tiene que ser otra variable.

Amit Ghosh
fuente
1

Tuve un problema similar. Dos componentes que se comunican entre sí estaban usando una cola.

El primer componente no estaba haciendo json.dumps antes de poner el mensaje en la cola. Entonces, la cadena JSON generada por el componente receptor estaba entre comillas simples. Esto estaba causando un error

 Expecting property name enclosed in double quotes

La adición de json.dumps comenzó a crear JSON con el formato correcto y se resolvió el problema.

Rahul Bagal
fuente
0

Usa la evalfunción.

Se encarga de la discrepancia entre comillas simples y dobles.

msamogh
fuente
NUNCA use eval en la entrada del usuario ni en los datos que vienen con la solicitud HTTP. Este es un gran problema de seguridad.
ElmoVanKielmo
0

Como las otras respuestas explican bien, el error se produce debido a caracteres de comillas no válidos que se pasan al módulo json.

En mi caso, seguí obteniendo ValueError incluso después de reemplazar 'con "en mi cadena. Lo que finalmente me di cuenta fue que algunos símbolos Unicode con forma de comillas se habían introducido en mi cadena:

           `  ´     

Para limpiar todos estos, simplemente puede pasar su cadena a través de una expresión regular:

import re

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

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

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

Me he encontrado con este problema varias veces cuando el JSON se ha editado a mano. Si alguien borra algo del archivo sin darse cuenta, puede arrojar el mismo error.

Por ejemplo, si falta su último JSON "}", arrojará el mismo error.

Entonces, si edita su archivo a mano, asegúrese de formatearlo como lo espera el decodificador JSON; de lo contrario, se encontrará con el mismo problema.

¡Espero que esto ayude!

Sneil
fuente
-2

Siempre es ideal utilizar el json.dumps()método. Para deshacerme de este error, utilicé el siguiente código

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