Python / Json: nom de propriété attendu entre guillemets


108

J'ai essayé de trouver un bon moyen de charger des objets JSON en Python. J'envoie ces données json:

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

au backend où il sera reçu sous forme de chaîne, alors je l'ai utilisé json.loads(data)pour l'analyser.

Mais à chaque fois, j'ai eu la même exception:

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

Je l'ai googlé mais rien ne semble fonctionner à part cette solution json.loads(json.dumps(data))qui ne me semble pas très efficace car elle accepte tout type de données même celles qui ne sont pas au format json.

Toutes les suggestions seront très appréciées.


18
Mon erreur n'était pas une double citation. J'ajoutais une virgule après la dernière paire clé-valeur comme nous le faisons en python. Vous ne faites pas cela en JSON.
Luv33preet

4
utilisez toujoursjson.dumps() plutôt que de simplement écrire python et espérez que la notation python fonctionnera dans votre lecteur JavaScript.
vy32

J'ai eu ce problème car j'ai pris le résultat d'un print(jsonpickle_deserialized_object_string)et j'ai essayé de l'utiliser. Pour une raison quelconque, print()change les citations de "à'
StingyJack

@ Luv33preet, merci, c'est résolu. mais je m'attends à ce que logger-msg soit une virgule manquante ou quelque chose du
genre

Réponses:


150

Ce:

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

n'est pas JSON.
Ce:

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

est JSON.

EDIT:
Certains commentateurs ont suggéré que ce qui précède ne suffit pas.
Spécification JSON - RFC7159 indique qu'une chaîne commence et se termine par des guillemets. C'est ça ".
Une quoute simple 'n'a pas de signification sémantique en JSON et n'est autorisée qu'à l'intérieur d'une chaîne.


4
Merci :) Je n'ai pas fait attention à cela, j'utilise le bon format json lors de l'envoi des données mais quand elles sont reçues en backend, les guillemets doubles sont remplacés par des simples! donc j'ai eu cette exception.
raeX le

25
Ce n'est pas une solution. Une solution lui dirait comment modifier la chaîne en json valide.
FistOfFury

2
@FistOfFury Je suis désolé mais votre déclaration est basée sur une fausse hypothèse selon laquelle une chaîne JSON invalide arbitraire peut être transformée de manière fiable par programme en une chaîne valide. Beaucoup de réponses à cette question tentent de résoudre le problème en remplaçant "par" et ainsi de suite. Dois-je vous donner des exemples simples de chaînes d'entrée qui briseront ces "solutions"? Apparemment, OP a compris que ce dont nous avons affaire n'est pas JSON et a pu continuer - j'ai accepté ma réponse. Astuce - la chaîne d'entrée ressemble plus à la sortie de la méthode Python dict .__ repr __ ().
ElmoVanKielmo

4
@ElmoVanKielmo ne change pas le fait que votre réponse est une affirmation, pas une réponse à la question. Vous ne fournissez aucun contexte ni explication. Les gens qui viennent ici à la recherche d'informations sur la question seront déçus. Vous avez peut-être aidé OP, mais d'autres pas tellement.
FistOfFury

Une simple déclaration claire aide souvent beaucoup. Surtout quand il y a plein d'autres réponses.
Ben

45

comme JSON autorise uniquement les chaînes entre guillemets, vous pouvez manipuler la chaîne comme ceci:

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

si votre JSON contient des guillemets simples échappés ( \'), vous devez utiliser le code suivant plus précis:

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

Cela remplacera toutes les occurrences de guillemets simples avec guillemets doubles dans la chaîne JSON str et dans ce dernier cas ne remplacera pas les guillemets simples échappés.

Vous pouvez également utiliser js-beautifyce qui est moins strict:

$ pip install jsbeautifier
$ js-beautify file.js

4
Ce n'est pas une bonne idée car il peut remplacer tout par "s qui est faux: EXEMPLE: 'c'est mauvais' ->" c'est "mauvais" -> chaîne malformée
Reihan_amn

@Reihan_amn J'ai ajouté une alternative regex plus précise pour les cas où des guillemets simples échappés sont utilisés.
éligible le

32

Dans mon cas, les doubles guillemets n'étaient pas un problème.

La dernière virgule m'a donné le même message d'erreur.

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

Pour supprimer cette virgule, j'ai écrit un code 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)

Et cela a fonctionné pour moi.


4
+1 Je peux le confirmer. La virgule de fin produit ce message d'erreur. Exemple:, echo '{"json":"obj",}' | python -m json.tool lorsqu'il est exécuté dans le shell, donne "Nom de la propriété attendue entre guillemets: ligne 1 colonne 15 (char 14)". Les virgules de fin ne sont pas du JSON légal, mais ce serait bien si le module Python JSON émettait un message d'erreur pertinent dans ce cas.
Laryx Decidua

7

Tout simplement, cette chaîne n'est pas un JSON valide. Comme le dit l'erreur, les documents JSON doivent utiliser des guillemets doubles.

Vous devez corriger la source des données.


6

J'ai vérifié vos données JSON

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

sur http://jsonlint.com/ et les résultats étaient:

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

en le modifiant avec la chaîne suivante, résolvez l'erreur JSON:

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

2
MERCI POUR CE LIEN!
WolVes

6

Les chaînes JSON doivent utiliser des guillemets doubles. La bibliothèque JSON python applique cela afin que vous ne puissiez pas charger votre chaîne. Vos données doivent ressembler à ceci:

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

Si ce n'est pas quelque chose que vous pouvez faire, vous pouvez utiliser à la ast.literal_eval()place dejson.loads()


3
Ce n'est pas une restriction de la bibliothèque Python, mais du format JSON lui-même.
Daniel Roseman le

Vous avez raison. Cependant, certains analyseurs JSON n'appliquent pas les guillemets doubles. Je mettrai à jour ma réponse.
alexbclay le

à condition que ce non-JSON n'ait jamais de guillemets doubles à l'intérieur de chaînes entre guillemets simples, tout ce que vous avez à faire est de remplacer tous les simples par des doubles avant de les appelerjson.loads()
nigel222

2
L'utilisation ast.literal_evalentraîne ValueError: malformed stringsi la chaîne JSON a une valeur booléenne.
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)

cela résoudra le problème.


3

Comme il est clairement indiqué par erreur, les noms doivent être placés entre guillemets doubles au lieu de guillemets simples. La chaîne que vous transmettez n'est tout simplement pas un JSON valide. Cela devrait ressembler à

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

2

J'ai utilisé cette méthode et j'ai réussi à obtenir le résultat souhaité. mon script

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

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

production

>>> 0

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

Cela a parfaitement bien fonctionné pour moi. Merci.


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

Bien que ce soit la bonne solution, mais cela peut conduire à un mal de tête s'il existe un JSON comme celui-ci -

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

Vous avez remarqué que la valeur "True" ? Utilisez ceci pour que les choses soient vérifiées deux fois pour les booléens. Cela couvrira ces cas -

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

Assurez-vous également de ne pas

x = json.loads(x)

Ce doit être une autre variable.


1

J'ai eu un problème similaire. Deux composants communiquant entre eux utilisaient une file d'attente.

Le premier composant ne faisait pas json.dumps avant de mettre le message dans la file d'attente. Ainsi, la chaîne JSON générée par le composant récepteur était entre guillemets simples. Cela provoquait une erreur

 Expecting property name enclosed in double quotes

L'ajout de json.dumps a commencé à créer un JSON correctement formaté et à résoudre le problème.


0

Utilisez la evalfonction.

Il prend en charge l'écart entre les guillemets simples et doubles.


N'utilisez JAMAIS eval sur l'entrée utilisateur ni les données fournies avec la requête HTTP. C'est un énorme problème de sécurité.
ElmoVanKielmo il y a

0

Comme les autres réponses l'expliquent bien, l'erreur se produit en raison de caractères de guillemet non valides passés au module json.

Dans mon cas, j'ai continué à obtenir ValueError même après avoir remplacé 'par "dans ma chaîne. Ce que j'ai finalement réalisé, c'est que certains symboles Unicode ressemblant à des guillemets avaient trouvé leur chemin dans ma chaîne:

           `  ´     

Pour nettoyer tout cela, vous pouvez simplement passer votre chaîne à travers une expression régulière:

import re

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

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

json_object = json.loads(parsed_string)

-1

J'ai rencontré ce problème plusieurs fois lorsque le JSON a été modifié à la main. Si quelqu'un devait supprimer quelque chose du fichier sans s'en apercevoir, cela peut générer la même erreur.

Par exemple, si votre dernier "}" JSON est manquant, il lancera la même erreur.

Donc, si vous modifiez votre fichier à la main, assurez-vous de le formater comme prévu par le décodeur JSON, sinon vous rencontrerez le même problème.

J'espère que cela t'aides!


-2

Il est toujours idéal d'utiliser la json.dumps()méthode. Pour me débarrasser de cette erreur, j'ai utilisé le code suivant

json.dumps(YOUR_DICT_STRING).replace("'", '"')
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.