Python / Json: è previsto il nome della proprietà racchiuso tra virgolette doppie


110

Ho cercato di trovare un buon modo per caricare oggetti JSON in Python. Invio questi dati JSON:

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

al backend dove verrà ricevuto come stringa, quindi l'ho usato json.loads(data)per analizzarlo.

Ma ogni volta ho ottenuto la stessa eccezione:

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

Ho cercato su Google ma niente sembra funzionare oltre a questa soluzione json.loads(json.dumps(data))che personalmente mi sembra poco efficiente dato che accetta qualsiasi tipo di dati anche quelli che non sono in formato json.

Ogni suggerimento sarà molto apprezzato.


18
Il mio errore non è stato una doppia citazione. Stavo aggiungendo una virgola dopo l'ultima coppia chiave-valore come facciamo in Python. Non lo fai in JSON.
Luv33preet

4
usa semprejson.dumps() piuttosto che scrivere semplicemente python e sperando che la notazione python funzioni nel tuo lettore JavaScript.
vy32

Ho avuto questo problema perché ho preso il risultato di a print(jsonpickle_deserialized_object_string)e ho provato a usarlo. Per qualche motivo print()cambia le virgolette da "a'
StingyJack

@ Luv33preet, grazie, ho risolto. ma mi aspetto che logger-msg sia virgola mancante o qualcosa del genere, ma questo errore non dice nulla al riguardo,
ganeshdeshmukh

vedere stackoverflow.com/a/63862387/1497139 per una soluzione rapida
Wolfgang Fahl

Risposte:


150

Questo:

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

non è JSON.
Questo:

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

è JSON.

EDIT:
Alcuni commentatori hanno suggerito che quanto sopra non è sufficiente.
Specifica JSON - RFC7159 afferma che una stringa inizia e finisce con virgolette. Cioè ".
Il quoute singolo 'non ha significato semantico in JSON ed è consentito solo all'interno di una stringa.


4
Grazie :) Non ho prestato attenzione a questo, sto usando il formato json corretto quando invio i dati ma quando vengono ricevuti dal backend le virgolette doppie vengono sostituite da quelle singole! quindi ho avuto quell'eccezione.
raeX

25
questa non è una soluzione. Una soluzione gli direbbe come modificare la stringa in json valido.
FistOfFury

2
@FistOfFury Mi dispiace ma la tua affermazione si basa sul falso presupposto che una stringa JSON non valida arbitraria possa essere trasformata in modo affidabile a livello di programmazione in una valida. Molte risposte a questa domanda cercano di affrontare il problema sostituendo "con" e così via. Devo darvi semplici esempi di stringhe di input che rompono queste "soluzioni"? Apparentemente OP ha capito che ciò di cui abbiamo a che fare non lo è JSON ed è stato in grado di procedere - ha accettato la mia risposta. Suggerimento: la stringa di input assomiglia più all'output del metodo Python dict .__ repr __ ().
ElmoVanKielmo

4
@ElmoVanKielmo non cambia il fatto che la tua risposta sia un'affermazione, non una risposta alla domanda. Non fornite alcun contesto o spiegazione. Le persone che vengono qui alla ricerca di informazioni sulla domanda rimarranno deluse. Potresti aver aiutato OP, ma altri non così tanto.
FistOfFury

Una semplice dichiarazione chiara spesso aiuta molto. Soprattutto, quando ci sono molte altre risposte in giro.
Ben

47

poiché JSON consente solo di racchiudere stringhe tra virgolette doppie, puoi manipolare la stringa in questo modo:

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

se il tuo JSON contiene virgolette singole con escape ( \'), dovresti utilizzare il codice seguente più preciso:

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

Questo sostituirà tutte le occorrenze di virgolette singole con virgolette doppie nella stringa JSON stre in quest'ultimo caso non sostituirà virgolette singole con escape.

Puoi anche usare js-beautifyche è meno rigoroso:

$ pip install jsbeautifier
$ js-beautify file.js

4
Non è una buona idea perché può sostituire tutte le "s", il che è sbagliato: ESEMPIO: "è cattivo" -> "è" cattivo "-> stringa malformata
Reihan_amn

@Reihan_amn Ho aggiunto un'alternativa regex più precisa per i casi in cui vengono utilizzate virgolette singole con escape.
idoneo il

la regexp dà un errore di sintassi
Wolfgang Fahl

@ WolfgangFahl puoi riprovare ora.
idoneo

grazie sto usando stackoverflow.com/a/63862387/1497139 invece ora
Wolfgang Fahl

33

Nel mio caso, le virgolette doppie non erano un problema.

L'ultima virgola mi ha dato lo stesso messaggio di errore.

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

Per rimuovere questa virgola, ho scritto un semplice codice.

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 questo ha funzionato per me.


4
+1 Posso confermarlo. La virgola finale produce questo messaggio di errore. Esempio:, echo '{"json":"obj",}' | python -m json.tool se eseguito nella shell, restituisce "Si prevede il nome della proprietà racchiuso tra virgolette doppie: riga 1 colonna 15 (carattere 14)". Le virgole finali non sono JSON legali, ma sarebbe bello se il modulo JSON Python emettesse un messaggio di errore rilevante in questo caso.
Laryx Decidua

7

Molto semplicemente, quella stringa non è JSON valido. Come dice l'errore, i documenti JSON devono utilizzare virgolette doppie.

È necessario correggere l'origine dei dati.


6

Ho controllato i tuoi dati JSON

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

in http://jsonlint.com/ ei risultati sono stati:

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

modificandolo nella seguente stringa si risolve l'errore JSON:

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

2
GRAZIE PER QUEL LINK!
WolVes

6

Le stringhe JSON devono utilizzare virgolette doppie. La libreria Python JSON lo applica in modo da non essere in grado di caricare la stringa. I tuoi dati devono avere questo aspetto:

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

Se non è qualcosa che puoi fare, potresti usare al ast.literal_eval()posto dijson.loads()


3
Questa non è una restrizione della libreria Python, ma del formato JSON stesso.
Daniel Roseman

Hai ragione. Tuttavia, alcuni parser JSON non applicano le virgolette doppie. Aggiornerò la mia risposta.
alexbclay

a condizione che questo non-JSON non abbia mai virgolette doppie all'interno di stringhe con virgolette singole, tutto ciò che devi fare è sostituire la stringa di tutti i singoli con i doppi prima di invocarejson.loads()
nigel222

2
L'utilizzo ast.literal_evalrisulterà ValueError: malformed stringse la stringa JSON ha un valore 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)

questo risolverà il problema.


3

Come dice chiaramente per errore, i nomi dovrebbero essere racchiusi tra virgolette doppie anziché virgolette singole. La stringa che passi semplicemente non è un JSON valido. Dovrebbe assomigliare

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

2

Ho usato questo metodo e sono riuscito a ottenere l'output desiderato. il mio copione

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

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

produzione

>>> 0

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

Questo ha funzionato perfettamente bene per me. Grazie.


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

Sebbene questa sia la soluzione corretta, ma potrebbe causare un bel mal di testa se esiste un JSON come questo -

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

Notato quel valore "Vero" ? Usalo per fare in modo che le cose vengano ricontrollate per i booleani. Questo coprirà quei casi -

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

Inoltre, assicurati di non fare

x = json.loads(x)

Deve essere un'altra variabile.


1

Ho avuto un problema simile. Due componenti che comunicavano tra loro utilizzavano una coda.

Il primo componente non stava eseguendo json.dumps prima di mettere il messaggio in coda. Quindi la stringa JSON generata dalla ricezione del componente era racchiusa tra virgolette singole. Ciò causava un errore

 Expecting property name enclosed in double quotes

L'aggiunta di json.dumps ha iniziato a creare un JSON formattato correttamente e ha risolto il problema.


0

Utilizzare il eval funzione.

Si occupa della discrepanza tra virgolette singole e doppie.


NON utilizzare MAI eval sull'input dell'utente né i dati forniti con la richiesta HTTP. Questo è un enorme problema di sicurezza.
ElmoVanKielmo

0

Come spiegano bene le altre risposte, l'errore si verifica a causa di virgolette non valide passate al modulo json.

Nel mio caso ho continuato a ricevere ValueError anche dopo aver sostituito 'con "nella mia stringa. Quello che ho finalmente capito è che alcuni simboli Unicode simili a virgolette si erano fatti strada nella mia stringa:

           `  ´     

Per pulire tutti questi puoi semplicemente passare la tua stringa attraverso un'espressione regolare:

import re

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

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

json_object = json.loads(parsed_string)

-1

Mi sono imbattuto in questo problema più volte quando il JSON è stato modificato a mano. Se qualcuno dovesse eliminare qualcosa dal file senza accorgersene, può generare lo stesso errore.

Ad esempio, se manca l'ultimo JSON "}", verrà generato lo stesso errore.

Quindi se modifichi il tuo file manualmente assicurati di formattarlo come previsto dal decoder JSON, altrimenti incorrerai nello stesso problema.

Spero che questo ti aiuti!


-2

È sempre ideale utilizzare il json.dumps()metodo. Per eliminare questo errore, ho utilizzato il codice seguente

json.dumps(YOUR_DICT_STRING).replace("'", '"')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.