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.


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

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.


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

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


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.


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.


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"
        }]
    }
}

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()


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.


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"}]}}

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

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.


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.


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.


0

Użyj evalfunkcji.

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


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)


-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!


-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("'", '"')
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.