Python / Json: oczekiwana nazwa właściwości ujęta w podwójne cudzysłowy

120

Próbowałem znaleźć dobry sposób ładowania obiektów JSON w Pythonie. Wysyłam te dane json:

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

do zaplecza, gdzie zostanie odebrany jako ciąg, a następnie json.loads(data)go przeanalizowałem.

Ale za każdym razem dostałem ten sam wyjątek:

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

Wyszukałem w Google, ale wydaje się, że nic nie działa poza tym rozwiązaniem, json.loads(json.dumps(data))które osobiście wydaje mi się nie tak wydajne, ponieważ akceptuje wszelkiego rodzaju dane, nawet te, które nie są w formacie json.

Wszelkie sugestie będą mile widziane.

raeX
źródło
20
Mój błąd nie polegał na podwójnym cytowaniu. Dodawałem przecinek po ostatniej parze klucz-wartość, tak jak robimy to w Pythonie. Nie robisz tego w JSON.
Luv33preet
4
zawsze używaj, json.dumps()a nie tylko pisząc Pythona i mając nadzieję, że notacja Pythona będzie działać w twoim czytniku JavaScript.
vy32
Miałem ten problem, ponieważ wziąłem wynik a print(jsonpickle_deserialized_object_string)i próbowałem go użyć. Z jakiegoś powodu print()zmienia notowania z "na'
StingyJack
@ Luv33preet, dzięki, udało mi się to rozwiązać. ale spodziewam się logger-msg jako brakującego przecinka czy czegoś takiego, ale ten błąd nic o tym nie mówi,
ganeshdeshmukh
zobacz stackoverflow.com/a/63862387/1497139, aby szybko naprawić
Wolfgang Fahl

Odpowiedzi:

161

To:

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

nie jest JSON.
To:

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

to JSON.

EDYCJA:
Niektórzy komentatorzy sugerowali, że powyższe nie wystarczy.
Specyfikacja JSON - RFC7159 stwierdza, że ​​ciąg znaków zaczyna się i kończy cudzysłowem. To jest ".
Pojedynczy quoute 'nie ma znaczenia semantycznego w JSON i jest dozwolony tylko wewnątrz ciągu.

ElmoVanKielmo
źródło
4
Dzięki :) Nie zwróciłem na to uwagi, używam poprawnego formatu json podczas wysyłania danych, ale gdy są one odbierane na zapleczu, podwójne cudzysłowy są zastępowane pojedynczymi! dlatego mam ten wyjątek.
raeX
35
to nie jest rozwiązanie. Rozwiązanie podpowiedziałoby mu, jak zmodyfikować łańcuch do prawidłowego formatu json.
FistOfFury
2
@FistOfFury Przykro mi, ale twoje oświadczenie opiera się na fałszywym założeniu, że dowolny nieprawidłowy ciąg JSON można niezawodnie przekształcić programowo w prawidłowy. Wiele odpowiedzi na to pytanie próbuje rozwiązać problem, zastępując „na” itd. Czy muszę podać proste przykłady ciągów wejściowych, które zepsują te „rozwiązania”? Najwyraźniej OP zrozumiał, że to, z czym mamy do czynienia, nie jest JSON i mogłem kontynuować - zaakceptowałem moją odpowiedź. Wskazówka - ciąg wejściowy wygląda bardziej jak wynik metody Python dict .__ repr __ ().
ElmoVanKielmo
4
@ElmoVanKielmo nie zmienia faktu, że Twoja odpowiedź jest stwierdzeniem, a nie odpowiedzią na pytanie. Nie podajesz kontekstu ani wyjaśnienia. Osoby, które przyjdą tutaj w poszukiwaniu informacji na temat pytania, będą rozczarowane. Być może pomogłeś OP, ale innym nie tak bardzo.
FistOfFury
Zwykłe, jasne stwierdzenie często bardzo pomaga. Zwłaszcza, gdy w pobliżu jest mnóstwo innych odpowiedzi.
Ben
55

Ponieważ JSON pozwala tylko na umieszczanie ciągów znaków w cudzysłowach, możesz manipulować łańcuchem w następujący sposób:

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

jeśli twój JSON zawiera pojedyncze cudzysłowy ( \'), to powinieneś użyć bardziej precyzyjnego następującego kodu:

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

Spowoduje to zastąpienie wszystkich wystąpień pojedynczego cudzysłowu podwójnym cudzysłowem w ciągu JSON, straw tym drugim przypadku nie spowoduje zastąpienia pojedynczych cudzysłowów ze zmianą znaczenia.

Możesz również użyć js-beautifymniej rygorystycznego:

$ pip install jsbeautifier
$ js-beautify file.js
elig
źródło
4
Nie jest to dobry pomysł, ponieważ może zastąpić wszystkie „s, co jest złe”: PRZYKŁAD: „jest zły” -> „jest zły” -> źle
sformułowany
@Reihan_amn Dodałem bardziej precyzyjną alternatywę wyrażenia regularnego dla przypadków, w których używane są pojedyncze cudzysłowy.
elig
wyrażenie regularne podaje błąd składni
Wolfgang Fahl
@WolfgangFahl, możesz teraz spróbować ponownie.
elig
thx Zamiast tego używam stackoverflow.com/a/63862387/1497139
Wolfgang Fahl
35

W moim przypadku podwójne cudzysłowy nie stanowiły problemu.

Ostatni przecinek dał mi ten sam komunikat o błędzie.

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

Aby usunąć ten przecinek, napisałem prosty kod.

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)

I to zadziałało dla mnie.

greentec
źródło
4
+1 Mogę to potwierdzić. Końcowy przecinek powoduje wyświetlenie tego komunikatu o błędzie. Przykład: echo '{"json":"obj",}' | python -m json.tool po uruchomieniu w powłoce zwraca „Oczekiwana nazwa właściwości ujęta w podwójne cudzysłowy: wiersz 1 kolumna 15 (znak 14)”. Końcowe przecinki nie są legalnym formatem JSON, ale byłoby miło, gdyby moduł Python JSON wyemitował w tym przypadku odpowiedni komunikat o błędzie.
Laryx Decidua
8

Po prostu ten ciąg nie jest prawidłowym kodem JSON. Jak mówi błąd, dokumenty JSON muszą używać podwójnych cudzysłowów.

Musisz naprawić źródło danych.

Daniel Roseman
źródło
7

Sprawdziłem Twoje dane JSON

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

w http://jsonlint.com/, a wyniki były następujące:

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

zmodyfikowanie go na następujący ciąg rozwiązuje błąd JSON:

{
    "http://example.org/about": {
        "http://purl.org/dc/terms/title": [{
            "type": "literal",
            "value": "Anna's Homepage"
        }]
    }
}
Yaron
źródło
2
DZIĘKUJEMY ZA TO LINK!
WolVes
7

Ciągi JSON muszą zawierać podwójne cudzysłowy. Biblioteka JSON python wymusza to, więc nie możesz załadować swojego ciągu. Twoje dane muszą wyglądać następująco:

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

Jeśli to nie jest coś, co możesz zrobić, możesz użyć ast.literal_eval()zamiastjson.loads()

alexbclay
źródło
3
To nie jest ograniczenie biblioteki Pythona, ale samego formatu JSON.
Daniel Roseman,
Masz rację. Jednak niektóre parsery JSON nie wymuszają podwójnych cudzysłowów. Zaktualizuję odpowiedź.
alexbclay
pod warunkiem, że ten nie-JSON nigdy nie ma podwójnych cudzysłowów w ciągach z pojedynczym cudzysłowem, wszystko, co musisz zrobić, to zamienić wszystkie pojedyncze json.loads()
znaki
2
Użycie ast.literal_evalspowoduje ValueError: malformed string, że ciąg JSON ma wartość logiczną.
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)

to rozwiąże problem.

balaji k
źródło
3

Jak jasno mówi się błędnie, nazwy powinny być ujęte w podwójne cudzysłowy zamiast w apostrofy. Przekazany ciąg nie jest prawidłowym plikiem JSON. Tak powinno wyglądać

{"http://example.org/about": {"http://purl.org/dc/terms/title": [{"type": "literal", "value": "Anna's Homepage"}]}}
Pavel Gurkov
źródło
2

Użyłem tej metody i udało mi się uzyskać pożądany wynik. mój skrypt

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

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

wynik

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

U mnie to zadziałało doskonale. Dzięki.

rohit9786
źródło
2
x = x.replace("'", '"')
j = json.loads(x)

Chociaż jest to poprawne rozwiązanie, ale może prowadzić do sporego bólu głowy, jeśli istnieje taki JSON -

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

Zauważyłeś tę „prawdziwą” wartość? Użyj tego, aby rzeczy były podwójnie sprawdzane pod kątem wartości logicznych. Obejmuje to te przypadki -

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

Upewnij się też, że nie robisz

x = json.loads(x)

To musi być inna zmienna.

Amit Ghosh
źródło
1

Miałem podobny problem. Dwa komponenty komunikujące się ze sobą korzystały z kolejki.

Pierwszy komponent nie wykonywał json.dumps przed umieszczeniem wiadomości w kolejce. Więc ciąg JSON wygenerowany przez komponent odbierający był w apostrofach. To powodowało błąd

 Expecting property name enclosed in double quotes

Dodanie json.dumps rozpoczęło tworzenie poprawnie sformatowanego JSON i rozwiązano problem.

Rahul Bagal
źródło
0

Użyj evalfunkcji.

Dba o rozbieżność między pojedynczymi i podwójnymi cudzysłowami.

msamogh
źródło
NIGDY nie używaj eval na wejściu użytkownika ani danych przychodzących z żądaniem HTTP. To jest ogromny problem bezpieczeństwa.
ElmoVanKielmo
0

Jak wyjaśniają inne odpowiedzi, błąd występuje z powodu nieprawidłowych znaków cudzysłowu przekazanych do modułu json.

W moim przypadku nadal uzyskać ValueError nawet po wymianie 'z "moim sznurkiem. W końcu zdałem sobie sprawę, że niektóre znaki Unicode podobne do cytatów znalazły się w moim ciągu:

 “  ”  ‛  ’  ‘  `  ´  ″  ′ 

Aby wyczyścić to wszystko, możesz po prostu przekazać ciąg przez wyrażenie regularne:

import re

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

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

json_object = json.loads(parsed_string)

Anders Solberg
źródło
-1

Wielokrotnie napotykałem ten problem, gdy JSON był edytowany ręcznie. Jeśli ktoś miałby coś usunąć z pliku nie zauważając, może wyrzucić ten sam błąd.

Na przykład, jeśli brakuje ostatniego „}” JSON, spowoduje to ten sam błąd.

Jeśli więc edytujesz plik ręcznie, upewnij się, że sformatowałeś go tak, jak oczekuje tego dekoder JSON, w przeciwnym razie napotkasz ten sam problem.

Mam nadzieję że to pomoże!

Sneil
źródło
-2

Stosowanie tej json.dumps()metody jest zawsze idealne . Aby pozbyć się tego błędu, użyłem następującego kodu

json.dumps(YOUR_DICT_STRING).replace("'", '"')
Michael Elimu
źródło