Mengapa Python tidak dapat menguraikan data JSON ini?

1439

Saya memiliki JSON ini dalam sebuah file:

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

Saya menulis skrip ini untuk mencetak semua data JSON:

import json
from pprint import pprint

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

pprint(data)

Program ini menimbulkan pengecualian, meskipun:

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)

Bagaimana saya bisa mengurai JSON dan mengekstrak nilainya?

michele
sumber
@kederrac Karena alasan yang diberikan: "Pertanyaan ini disebabkan oleh kesalahan ketik atau masalah yang tidak dapat lagi direproduksi." Json tidak valid.
Rob
@kederrac Masalah ini disebabkan oleh kesalahan dalam penggunaan bukan karena dapat direproduksi.
Rob

Jawaban:

2128

Data Anda bukan format JSON yang valid . Anda miliki []ketika Anda harus memiliki {}:

  • []adalah untuk array JSON, yang disebut listdengan Python
  • {}adalah untuk objek JSON, yang disebut dictdengan Python

Beginilah tampilan file JSON Anda:

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

Kemudian Anda dapat menggunakan kode Anda:

import json
from pprint import pprint

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

pprint(data)

Dengan data, kini Anda juga dapat menemukan nilai seperti:

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

Cobalah itu dan lihat apakah itu masuk akal.

Justin Peel
sumber
1
Ok jadi saya harus mengontrol kode saya karena file json ini dihasilkan dari objek java. Terima kasih.
michele
5
Terima kasih atas solusinya. Saya mendapatkan simbol unicode saat mencetaknya. (mis. u'valore '). Bagaimana cara mencegahnya?
diaryfolio
6
Bagus tapi python menambahkan u'sebelum setiap tombol. Ada yang tahu kenapa?
CodyBugstein
7
Itu sebabnya teks Anda adalah tipe unicode bukan string. Sering kali lebih baik memiliki teks dalam unicode untuk umlaut Jerman dan untuk berbagi hasil teks dengan modul / program lain, dll. Jadi kamu baik-baik saja!
Michael P
2
Saya ingin melakukan pengamatan yang semoga bermanfaat, dan pasti ironis. Saya menemukan modul cetakan lebih rendah dari modul json untuk pencetakan cantik-json. Jika Anda mencoba keduanya, saya pikir Anda akan setuju. Untuk menampilkan dan men-debug struktur data json saya, saya telah melakukan: output = json.dumps (data_structure, indent = 2, sort_keys = True) print (output) Saya pikir Anda akan menemukan kontrol indent, pengurutan, dan kecerdasan line-wrapping dalam metode dumps () sesuai keinginan Anda. Jika pemikiran saya salah, tolong beri tahu saya.
Larold
307

Anda data.jsonakan terlihat seperti ini:

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

Kode Anda harus:

import json
from pprint import pprint

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

Perhatikan bahwa ini hanya berfungsi di Python 2.6 dan lebih tinggi, karena ini tergantung pada- withpernyataan . Dalam penggunaan Python 2.5 from __future__ import with_statement, dalam Python <= 2.4, lihat jawaban Justin Peel , yang menjadi dasar jawaban ini.

Anda sekarang juga dapat mengakses nilai tunggal seperti ini:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'
Bengt
sumber
7
Saya mendapat downvote tentang ini. Mungkin tidak jelas, mengapa saya pikir jawaban lain diperlukan. Catatan tambahan tentang kompatibilitas pernyataan-dengan.
Bengt
Maaf untuk memutar kembali, tetapi kode yang disarankan akan membuat data_file opened lebih lama dari yang diperlukan.
Bengt
Mengacu pada dokumentasi 2.6 ( docs.python.org/2.6/library/io.html ), membuka file dalam konteks "with" akan secara otomatis menutup file.
Steve S.
1
@SteveS. Ya, tetapi tidak sebelum konteksnya ditinggalkan. pprinting dalam withkonteks-membuat data_fileterbuka lebih lama.
Bengt
1
@GayanPathirage Anda mengaksesnya seperti data["om_points"], data["masks"]["id"]. Idenya adalah Anda dapat mencapai level apa pun dalam kamus dengan menentukan 'jalur kunci'. Jika Anda mendapatkan KeyErrorpengecualian itu berarti kunci tidak ada di jalur. Carilah kesalahan ketik atau periksa struktur kamus Anda.
Nuhman
71

Jawaban Justin Peel sangat membantu, tetapi jika Anda menggunakan Python 3 membaca JSON harus dilakukan seperti ini:

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

Catatan: gunakan json.loadssebagai ganti json.load. Dalam Python 3, json.loadsmengambil parameter string. json.loadmengambil parameter objek seperti file. data_file.read()mengembalikan objek string.

Sejujurnya, saya tidak berpikir itu masalah untuk memuat semua data json ke dalam memori kebanyakan kasus.

Geng Jiawen
sumber
10
Mengapa harus json.loaddihindari dalam mendukung .loadsPython 3?
Zearin
10
Halaman yang Anda tautkan tidak mengatakan apa-apa tentang menghindari load.
Dan Hulme
28
Jawaban ini membaca seluruh file ke memori ketika tidak harus dan menyarankan bahwa dalam Python 3 file JSON tidak dapat dibaca dengan malas, yang tidak benar. Maaf, tapi itu jelas downvote.
Łukasz Rogalski
10
Jawaban ini tidak akurat. Tidak ada alasan untuk tidak menggunakan json.load dengan file handler terbuka di python3. Maaf untuk downvote, tetapi sepertinya Anda tidak membaca komentar di atas dengan sangat hati-hati.
dusktreader
5
+1 Jawaban ini luar biasa! Terima kasih untuk itu dan menarik saya dari jauh untuk mencari fungsi yang dapat menggunakan string karena saya hanya bekerja dengan string dan permintaan jaringan yang bukan file!
baru
54
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))
pengguna1743724
sumber
8
ini adalah solusi yang tepat jika Anda memiliki beberapa objek json di file. json.loadstidak mendekode beberapa objek json. Jika tidak, Anda mendapatkan kesalahan 'Data Ekstra'.
yasin_alm
Ini jawaban terbaik. Kalau tidak, itu memberikan kesalahan 'Data Ekstra'.
Earthx9
39
Memiliki objek mutliple json dalam file berarti bahwa file itu sendiri sebenarnya tidak valid json. Jika Anda memiliki beberapa objek untuk disertakan dalam file json, mereka harus dimasukkan dalam array di tingkat atas file.
dusktreader
Memiliki beberapa objek json dalam file berarti file tersebut bukan objek json tunggal. Itu agak jelas. Membuat array tunggal dari objek adalah solusi yang jelas. Tetapi JSON secara desain dihentikan secara eksplisit, di hampir setiap tingkatan (oleh }, ]atau "). Oleh karena itu Anda memang dapat menggabungkan beberapa objek dalam satu string atau file tunggal, tanpa ambiguitas. Masalahnya di sini adalah bahwa parser mengharapkan satu objek gagal ketika melewati lebih dari satu objek.
MSalters
Iklan yang menyimpan beberapa objek JSON dalam satu file: ada "standar" untuk itu - jsonlines.org/example in .jsonl(json lines), objek dipisahkan oleh karakter baris baru yang membuat pra-pemrosesan untuk parsing sepele, dan memungkinkan untuk dengan mudah membagi / batch file tanpa khawatir tentang penanda awal / akhir.
Sebi
13

"Ultra JSON" atau hanya "ujson" dapat menangani memiliki []input file JSON Anda. Jika Anda membaca file input JSON ke dalam program Anda sebagai daftar elemen JSON; seperti, [{[{}]}, {}, [], etc...]ujson dapat menangani urutan daftar kamus yang sewenang-wenang, kamus daftar.

Anda dapat menemukan ujson dalam indeks paket Python dan API hampir identik dengan jsonpustaka bawaan Python .

ujson juga jauh lebih cepat jika Anda memuat file JSON yang lebih besar. Anda dapat melihat detail kinerja dibandingkan dengan pustaka JSON Python lain di tautan yang sama.

moeabdol
sumber
9

Jika Anda menggunakan Python3, Anda dapat mencoba mengubah ( connection.jsonfile) JSON Anda menjadi:

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

Kemudian gunakan kode berikut:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1
sushmit
sumber
1
ini juga bekerja di 2.7.5
siddardha
17
ini membiarkan pegangan file terbuka. menggunakan withpernyataan akan lebih baik
Corey Goldberg
6

Di sini Anda pergi dengan data.jsonfile yang dimodifikasi :

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

Anda dapat memanggil atau mencetak data pada konsol dengan menggunakan baris berikut:

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

Output yang diharapkan untuk print(data_item['parameters'][0]['id']):

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

Output yang diharapkan untuk print(data_item['parameters'][0]['id']):

valore
JoboFive
sumber
Jika kita ingin menambahkan kolom untuk menghitung berapa banyak pengamatan yang dimiliki "peta", bagaimana kita bisa menulis fungsi ini?
Chenxi
5

Ada dua tipe dalam penguraian ini.

  1. Parsing data dari file dari jalur sistem
  2. Parsing JSON dari URL jarak jauh.

Dari sebuah file, Anda dapat menggunakan yang berikut ini

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

Arktik ini menjelaskan penguraian penuh dan mendapatkan nilai menggunakan dua skenario. Parsing JSON menggunakan Python

Bibin Wilson
sumber
4

Sebagai pengguna python3 ,

Perbedaan antara loaddan loadsmetode ini penting terutama ketika Anda membaca data json dari file.

Sebagaimana dinyatakan dalam dokumen:

json.load:

Deserialize fp (a .read () - file teks pendukung atau file biner yang berisi dokumen JSON) ke objek Python menggunakan tabel konversi ini.

json.loads:

json.loads: Deserialize s (str, byte atau instance bytearray yang berisi dokumen JSON) ke objek Python menggunakan tabel konversi ini.

Metode json.load dapat langsung membaca dokumen json yang dibuka karena ia dapat membaca file biner.

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

Akibatnya, data json Anda tersedia dalam format yang ditentukan berdasarkan tabel konversi ini:

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

muratgozel
sumber
Bagaimana ini menjawab pertanyaan yang diajukan? Pengguna menggunakan metode yang tepat untuk memuat file json.
Raj006