JSON ValueError: Oczekiwano nazwy właściwości: wiersz 1 kolumna 2 (znak 1)

97

Mam problem z używaniem json.loads do konwersji na obiekt dict i nie mogę dowiedzieć się, co robię źle.

ValueError: Expecting property name: line 1 column 2 (char 1)

Oto mój kod:

from kafka.client import KafkaClient
from kafka.consumer import SimpleConsumer
from kafka.producer import SimpleProducer, KeyedProducer
import pymongo
from pymongo import MongoClient
import json

c = MongoClient("54.210.157.57")
db = c.test_database3
collection = db.tweet_col

kafka = KafkaClient("54.210.157.57:9092")

consumer = SimpleConsumer(kafka,"myconsumer","test")
for tweet in consumer:
    print tweet.message.value
    jsonTweet=json.loads(({u'favorited': False, u'contributors': None})
    collection.insert(jsonTweet)

Jestem prawie pewien, że błąd występuje w drugim do ostatniego wierszu

jsonTweet=json.loads({u'favorited': False, u'contributors': None})

ale nie wiem, co zrobić, żeby to naprawić. Każda rada będzie mile widziana.

dredbound
źródło
3
czy widzisz tam błąd składni? Błądzący "czy to błąd kopiowania wklejania?
karthikr
Jaki był ciąg JSON wydrukowany w linii print tweet.message.value?
Luke Woodward,
1
Wysyłane ValueErrorjest z powodu błędu w danych wejściowych JSON, a nie problemu w kodzie. (Oprócz zaginionego, "który powinien normalnie wysłać, SyntaxErrorwięc zakładam, że to tylko błąd kopiowania wklejania.)
Cld
(Nawiasem mówiąc, utf_8 jest domyślnym kodowaniem dla json.loads, więc nie trzeba go wskazywać.)
Cld
Dzięki za wkład. Redagowałem pytanie, teraz powinno być jaśniejsze.
dredbound,

Odpowiedzi:

84

json.loadszaładuje ciąg json do pythona dict, json.dumpszrzuci python dictdo łańcucha json, na przykład:

>>> json_string = '{"favorited": false, "contributors": null}'
'{"favorited": false, "contributors": null}'
>>> value = json.loads(json_string)
{u'favorited': False, u'contributors': None}
>>> json_dump = json.dumps(value)
'{"favorited": false, "contributors": null}'

Więc ta linia jest niepoprawna, ponieważ próbujesz loadużyć Pythona dicti json.loadsoczekuje prawidłowego, json stringktóry powinien mieć <type 'str'>.

Więc jeśli próbujesz załadować json, powinieneś zmienić to, co ładujesz, aby wyglądało jak json_stringpowyżej, lub powinieneś to zrzucić. To tylko moje najlepsze przypuszczenie na podstawie podanych informacji. Co próbujesz osiągnąć?

Nie musisz także określać uprzed znakami, jak wspomniano w komentarzach @Cld.

Tak_To jest_Me
źródło
2
json.loads załaduje -> obiekt json <- do dyktu pythona - To jest sprzeczne z tym, co mówią dokumenty, a nawet z tym, co robi twój własny kod - używasz load () na łańcuchu, a nie json obiekt .
7stud
Tak @ 7stud, masz rację, ładuje ciąg. Ale musi to być prawidłowy ciąg json. Zaktualizowałem odpowiedź.
Yep_It's_Me
187

Napotkałem inny problem, który zwraca ten sam błąd.

Problem z pojedynczą wyceną

Użyłem łańcucha json z pojedynczymi cudzysłowami :

{
    'property': 1
}

Ale json.loadsakceptuje tylko podwójne cudzysłowy dla właściwości json :

{
    "property": 1
}

Ostatni problem z przecinkiem

json.loads nie akceptuje ostatniego przecinka:

{
  "property": "text", 
  "property2": "text2",
}

Rozwiązanie: astaby rozwiązać problemy z pojedynczym cytatem i ostatnim przecinkiem

Możesz użyć ast(część standardowej biblioteki dla Pythona 2 i 3) do tego przetwarzania. Oto przykład :

import ast
# ast.literal_eval() return a dict object, we must use json.dumps to get JSON string
import json

# Single quote to double with ast.literal_eval()
json_data = "{'property': 'text'}"
json_data = ast.literal_eval(json_data)
print(json.dumps(json_data))
# Displays : {"property": "text"}

# ast.literal_eval() with double quotes
json_data = '{"property": "text"}'
json_data = ast.literal_eval(json_data)
print(json.dumps(json_data))
# Displays : {"property": "text"}

# ast.literal_eval() with final coma
json_data = "{'property': 'text', 'property2': 'text2',}"
json_data = ast.literal_eval(json_data)
print(json.dumps(json_data))
# Displays : {"property2": "text2", "property": "text"}

Użycie astzapobiegnie problemom z pojedynczymi cudzysłowami i końcowymi przecinkami, interpetując JSON, tak jak słownik Pythona (więc musisz postępować zgodnie ze składnią słownika Pythona). To całkiem dobra i bezpieczna alternatywa eval()funkcji dla struktur literalnych.

Dokumentacja Pythona ostrzegła nas przed użyciem dużego / złożonego ciągu:

Ostrzeżenie Możliwe jest zawieszenie interpretera Pythona za pomocą wystarczająco dużego / złożonego ciągu znaków ze względu na ograniczenia głębokości stosu w kompilatorze Pythona AST.

json.dumps z pojedynczymi cudzysłowami

Aby json.dumpsłatwo używać pojedynczych cudzysłowów, możesz użyć tego kodu:

import ast
import json

data = json.dumps(ast.literal_eval(json_data_single_quote))

ast dokumentacja

ast Python 3 doc

ast Python 2 doc

Narzędzie

Jeśli często edytujesz JSON, możesz użyć CodeBeautify . Pomaga naprawić błąd składni i zminimalizować / upiększyć JSON.

Mam nadzieję, że to pomoże.

Samuel Dauzon
źródło
10
  1. zamień wszystkie pojedyncze cudzysłowy na podwójne
  2. zamień „u” ”ze swoich ciągów na„ ”” ... więc po prostu przekonwertuj wewnętrzne unicodes na ciągi przed załadowaniem ciągu do json
>> strs = "{u'key':u'val'}"
>> strs = strs.replace("'",'"')
>> json.loads(strs.replace('u"','"'))
Vinay Pande
źródło
1
bardziej Pythonowym sposobem byłoby użycie ast.literal_eval ("{u'key ': u'val'}"). Zajmie się wszystkimi problemami związanymi z formatem
Vinay Pande,
json.loads (strs.replace ('u' ',' ')) nie działa. Oto poniższy błąd, Traceback (ostatnie połączenie): Plik „<stdin>”, wiersz 1, w <module> Plik "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", wiersz 338, w ładowaniu zwraca _default_decoder.decode (s) obj, end = self.scan_once (s , idx) ValueError: Oczekiwanie nazwy właściwości: wiersz 1 kolumna 2 (znak 1)
Sanjay Pradeep
4

Wszystkie inne odpowiedzi mogą odpowiedzieć na twoje zapytanie, ale napotkałem ten sam problem, który był spowodowany błędem, ,który dodałem na końcu mojego ciągu json w następujący sposób:

{
 "key":"123sdf",
 "bus_number":"asd234sdf",
}

W końcu działało, kiedy usunąłem dodatkowe w ,ten sposób:

{
 "key":"123sdf",
 "bus_number":"asd234sdf"
}

Mam nadzieję, że to pomoże! Twoje zdrowie.

Rishabh Agrahari
źródło
1
dobry, chociaż jest to już objęte odpowiedzią
Jedemy
@fedorqui Ta część została dodana po mojej odpowiedzi ( stackoverflow.com/posts/36599122/revisions ) Teraz możesz dać +1 :)
Rishabh Agrahari
1
och, masz rację! Został dodany do stycznia 2018 roku. Przeprasza i +1 :)
fedorqui 'SO przestać krzywdzić'
0

używany ast, przykład

In [15]: a = "[{'start_city': '1', 'end_city': 'aaa', 'number': 1},\
...:      {'start_city': '2', 'end_city': 'bbb', 'number': 1},\
...:      {'start_city': '3', 'end_city': 'ccc', 'number': 1}]"
In [16]: import ast
In [17]: ast.literal_eval(a)
Out[17]:
[{'end_city': 'aaa', 'number': 1, 'start_city': '1'},
 {'end_city': 'bbb', 'number': 1, 'start_city': '2'},
 {'end_city': 'ccc', 'number': 1, 'start_city': '3'}]
xin.chen
źródło
0

Inny przypadek, w którym spotkałem się z tym, miał miejsce, gdy użyłem echodo przesłania kodu JSON do mojego skryptu w Pythonie i niedbale zawiniłem ciąg JSON w podwójne cudzysłowy:

echo "{"thumbnailWidth": 640}" | myscript.py

Zauważ, że sam ciąg JSON zawiera cudzysłowy i powinienem był zrobić:

echo '{"thumbnailWidth": 640}' | myscript.py

Jak to było, to co otrzymał skrypt python: {thumbnailWidth: 640}; podwójne cudzysłowy zostały skutecznie usunięte.

Jim Hoagland
źródło