Dlaczego Python nie może przeanalizować tych danych JSON?


1438

Mam ten JSON w pliku:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [
        "id": "valore"
    ],
    "om_points": "value",
    "parameters": [
        "id": "valore"
    ]
}

Napisałem ten skrypt, aby wydrukować wszystkie dane JSON:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

Ten program zgłasza wyjątek:

Traceback (most recent call last):
  File "<pyshell#1>", line 5, in <module>
    data = json.load(f)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 13 column 13 (char 213)

Jak mogę przeanalizować JSON i wyodrębnić jego wartości?


@kederrac Z podanego powodu: „To pytanie było spowodowane literówką lub problemem, którego nie można już odtworzyć”. Json jest nieprawidłowy.
— Rob

@kederrac Problem jest spowodowany błędem w użyciu, nie dlatego, że można go odtworzyć.
— Rob

Odpowiedzi:


2127

Twoje dane są nieprawidłowe w formacie JSON . Masz, []kiedy powinieneś {}:

  • []są dla tablic JSON, które są wywoływane listw Pythonie
  • {}dotyczą obiektów JSON, które są wywoływane dictw języku Python

Oto jak powinien wyglądać Twój plik JSON:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": {
        "id": "valore"
    },
    "om_points": "value",
    "parameters": {
        "id": "valore"
    }
}

Następnie możesz użyć swojego kodu:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

Dzięki danym możesz teraz znaleźć takie wartości:

data["maps"][0]["id"]
data["masks"]["id"]
data["om_points"]

Wypróbuj je i sprawdź, czy to zaczyna mieć sens.


1
Ok, więc muszę kontrolować mój kod, ponieważ ten plik Json jest generowany z obiektu Java. Dzięki.
— michele

5
Dzięki za rozwiązanie. Podczas drukowania otrzymuję symbol Unicode. (np. u'valore '). Jak temu zapobiec?
— diaryfolio

6
Ładne, ale python dodaje u'przed każdym kluczem. Masz pomysł, dlaczego?
— CodyBugstein,

7
Dlatego twój tekst to Unicode, a nie string. Większość czasu lepiej jest mieć tekst w Unicode dla niemieckich umlautów i do dzielenia się wynikami tekstowymi z innymi modułami / programami itp. Więc jesteś dobry!
— Michael P.

2
Chciałbym dokonać obserwacji, która, mam nadzieję, jest pomocna i zdecydowanie ironiczna. Uważam, że moduł pprint jest gorszy od modułu json dla ładnego drukowania jsona. Jeśli spróbujesz obu, myślę, że się zgodzisz. Aby wyświetlić i debugować moje struktury danych json, robiłem: output = json.dumps (data_structure, indent = 2, sort_keys = True) print (output) Myślę, że znajdziesz kontrolę wcięcia, sortowanie i inteligentny zawijanie wierszy w metodzie dumps () tak, aby ci się podobało. Jeśli moje myślenie jest błędne, proszę dać mi znać.
— Larold,

307

Twój data.jsonpowinien wyglądać tak:

{
 "maps":[
         {"id":"blabla","iscategorical":"0"},
         {"id":"blabla","iscategorical":"0"}
        ],
"masks":
         {"id":"valore"},
"om_points":"value",
"parameters":
         {"id":"valore"}
}

Twój kod powinien być:

import json
from pprint import pprint

with open('data.json') as data_file:    
    data = json.load(data_file)
pprint(data)

Zauważ, że działa to tylko w Pythonie 2.6 i withnowszych wersjach , ponieważ zależy to od -statement . W Pythonie 2.5 from __future__ import with_statement, w Pythonie <= 2.4, patrz odpowiedź Justina Peela , na której opiera się ta odpowiedź.

Możesz teraz uzyskać dostęp do pojedynczych wartości takich jak to:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'

7
Mam opinię na ten temat. Może nie było jasne, dlaczego uważam, że potrzebna jest inna odpowiedź. Dodano uwagę na temat zgodności z instrukcją with.
— Bengt

Przepraszamy za wycofanie, ale sugerowany kod będzie data_file openedytowany dłużej niż to konieczne.
— Bengt,

Odwołując się do dokumentacji 2.6 ( docs.python.org/2.6/library/io.html ), otwarcie pliku w kontekście „z” spowoduje automatyczne zamknięcie pliku.
— Steve S.

1
@SteveS. Tak, ale nie przed opuszczeniem kontekstu. pprinting w kontekście with-dotrzymuje data_fileotwarte dłużej.
— Bengt,

1
@GayanPathirage go otworzyć jak data["om_points"], data["masks"]["id"]. Chodzi o to, że można osiągnąć dowolny poziom w słowniku, określając „ścieżki klucza”. Jeśli otrzymasz KeyErrorwyjątek, oznacza to, że klucz nie istnieje na ścieżce. Uważaj na literówki lub sprawdź strukturę swojego słownika.
— Nuhman,

71

Odpowiedź Justina Peela jest naprawdę pomocna, ale jeśli używasz języka Python 3, czytanie JSON powinno wyglądać następująco:

with open('data.json', encoding='utf-8') as data_file:
    data = json.loads(data_file.read())

Uwaga: użyj json.loadszamiast json.load. W Pythonie 3 json.loadspobiera parametr ciągu. json.loadpobiera parametr obiektu podobny do pliku. data_file.read()zwraca obiekt ciągu.

Szczerze mówiąc, nie sądzę, aby w większości przypadków ładowanie wszystkich danych Json do pamięci stanowiło problem.


10
Dlaczego należy json.loadtego unikać .loadsw Pythonie 3?
— Zearin,

10
Strona, do której prowadzi link, nie mówi nic o unikaniu load.
— Dan Hulme

28
Ta odpowiedź czyta cały plik do pamięci, gdy nie jest to konieczne, i sugeruje, że w Pythonie 3 plików JSON nie można odczytać leniwie, co jest nieprawdą. Przepraszam, ale to oczywista opinia.
— Łukasz Rogalski,

10
Ta odpowiedź nie jest dokładna. Nie ma powodu, aby nie używać pliku json.load z otwartą procedurą obsługi plików w python3. Przepraszamy za przegłosowanie, ale nie wydaje się, abyś uważnie przeczytał powyższe komentarze.
— dusktreader 30.09.16

5
+1 Ta odpowiedź jest świetna! Dziękuję za to i odciągnąłem mnie od szukania funkcji, która może używać łańcuchów, ponieważ pracuję tylko z łańcuchami i żądaniami sieci, które nie są plikami!
— newpeople

54
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))

8
jest to poprawne rozwiązanie, jeśli w pliku znajduje się wiele obiektów Json. json.loadsnie dekoduje wielu obiektów Json. W przeciwnym razie pojawi się błąd „Dodatkowe dane”.
— yasin_alm

To najlepsza odpowiedź. W przeciwnym razie pojawia się błąd „Dodatkowe dane”.
— Earthx9

39
Posiadanie wielu obiektów json w pliku oznacza, że ​​sam plik nie jest tak naprawdę prawidłowym plikiem json. Jeśli masz wiele obiektów do uwzględnienia w pliku json, powinny one być zawarte w tablicy na najwyższym poziomie pliku.
— dusktreader 30.09.16

Posiadanie wielu obiektów Json w pliku oznacza, że ​​plik nie jest pojedynczym obiektem Json. To trochę oczywiste. Utworzenie jednej tablicy z obiektów jest oczywistym obejściem. Ale JSON jest zgodne z projektem jednoznacznie rozwiązana, na prawie każdym poziomie (przez }, ]lub "). W związku z tym można rzeczywiście łączyć wiele obiektów w jednym ciągu lub w jednym pliku, bez dwuznaczności. Problem polega na tym, że analizator składni oczekujący pojedynczego obiektu zawiedzie, gdy zostanie przekazany więcej niż jeden obiekt.
— MSalters

Reklama przechowująca wiele obiektów JSON w jednym pliku: istnieje do tego „standard” - jsonlines.org/examples w .jsonl(linie json), obiekty są oddzielone znakiem nowej linii, co sprawia, że ​​wstępne przetwarzanie do parsowania jest banalne i pozwala do łatwego dzielenia / grupowania plików bez obawy o znaczniki początkowe / końcowe.
— Sebi,

13

„Ultra JSON” lub po prostu „ujson” poradzi sobie z []wejściem do pliku JSON. Jeśli czytasz plik wejściowy JSON w swoim programie jako listę elementów JSON; takie jak [{[{}]}, {}, [], etc...]ujson może obsłużyć dowolną dowolną kolejność list słowników, słowników list.

Możesz znaleźć ujson w indeksie pakietu Python, a interfejs API jest prawie identyczny z biblioteką wbudowaną w Python json.

ujson jest również znacznie szybszy, jeśli ładujesz większe pliki JSON. Możesz zobaczyć szczegóły dotyczące wydajności w porównaniu z innymi bibliotekami JSON Pythona w tym samym podanym linku.


9

Jeśli używasz Python3, możesz spróbować zmienić swój ( connection.jsonplikowy) JSON na:

{
  "connection1": {
    "DSN": "con1",
    "UID": "abc",
    "PWD": "1234",
    "connection_string_python":"test1"
  }
  ,
  "connection2": {
    "DSN": "con2",
    "UID": "def",
    "PWD": "1234"
  }
}

Następnie za pomocą następującego kodu:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1

1
działa to również w wersji 2.7.5
— siddardha

17
pozostawia to otwarty uchwyt pliku. użycie withoświadczenia byłoby lepsze
— Corey Goldberg,

6

Proszę przejść ze zmodyfikowanym data.jsonplikiem:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [{
        "id": "valore"
    }],
    "om_points": "value",
    "parameters": [{
        "id": "valore"
    }]
}

Możesz zadzwonić lub wydrukować dane na konsoli, używając poniższych wierszy:

import json
from pprint import pprint
with open('data.json') as data_file:
    data_item = json.load(data_file)
pprint(data_item)

Oczekiwany wynik dla print(data_item['parameters'][0]['id']):

{'maps': [{'id': 'blabla', 'iscategorical': '0'},
          {'id': 'blabla', 'iscategorical': '0'}],
 'masks': [{'id': 'valore'}],
 'om_points': 'value',
 'parameters': [{'id': 'valore'}]}

Oczekiwany wynik dla print(data_item['parameters'][0]['id']):

valore

Jeśli chcielibyśmy dodać kolumnę zliczającą liczbę obserwacji w „mapach”, jak moglibyśmy napisać tę funkcję?
— Chenxi

5

Istnieją dwa typy tej analizy.

  1. Analizowanie danych z pliku ze ścieżki systemowej
  2. Analizowanie JSON ze zdalnego adresu URL.

Z pliku można użyć następujących opcji

import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print json['value']

W tym artykule wyjaśniono pełne analizowanie i uzyskiwanie wartości przy użyciu dwóch scenariuszy. Analizowanie JSON przy użyciu Pythona


4

Jako użytkownik python3 ,

Różnica pomiędzy loadi loadsmetod jest szczególnie ważne podczas odczytu danych z pliku json.

Jak stwierdzono w dokumentach:

json.load:

Deserializuj fp (a .read () - obsługujący plik tekstowy lub plik binarny zawierający dokument JSON) do obiektu Python przy użyciu tej tabeli konwersji.

json.loads:

json.loads: Deserializuj s (instancję str, bytes lub bajtrayray zawierającą dokument JSON) do obiektu Python przy użyciu tej tabeli konwersji.

Metoda json.load może bezpośrednio odczytać otwarty dokument json, ponieważ jest w stanie odczytać plik binarny.

with open('./recipes.json') as data:
  all_recipes = json.load(data)

W rezultacie Twoje dane Json są dostępne w formacie określonym zgodnie z tą tabelą konwersji:

https://docs.python.org/3.7/library/json.html#json-to-py-table


Jak to jest odpowiedź na zadane pytanie? Użytkownik używał właściwej metody, aby załadować plik json.
— Raj006,
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.