ทำไมหลามถึงไม่แยกวิเคราะห์ข้อมูล JSON นี้


1439

ฉันมี JSON นี้ในไฟล์:

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

ฉันเขียนสคริปต์นี้เพื่อพิมพ์ข้อมูล JSON ทั้งหมด:

import json
from pprint import pprint

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

pprint(data)

โปรแกรมนี้ทำให้เกิดข้อยกเว้นแม้ว่า:

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)

ฉันจะแยกวิเคราะห์ JSON และแยกค่าได้อย่างไร


@kederrac ด้วยเหตุผลที่ได้รับ: "คำถามนี้เกิดจากการพิมพ์ผิดหรือปัญหาที่ไม่สามารถทำซ้ำได้อีกต่อไป" json ไม่ถูกต้อง
Rob

@kederrac ปัญหาเกิดจากข้อผิดพลาดในการใช้งานไม่ใช่เพราะมันสามารถทำซ้ำได้
Rob

คำตอบ:


2128

ข้อมูลของคุณไม่ใช่รูปแบบJSON ที่ถูกต้อง คุณมี[]เมื่อคุณควรจะมี{}:

  • []ใช้สำหรับอาร์เรย์ JSON ซึ่งถูกเรียกlistใน Python
  • {}ใช้สำหรับวัตถุ JSON ซึ่งเรียกdictใน Python

นี่คือลักษณะของไฟล์ JSON ของคุณ:

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

จากนั้นคุณสามารถใช้รหัสของคุณ:

import json
from pprint import pprint

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

pprint(data)

ด้วยข้อมูลขณะนี้คุณสามารถค้นหาค่าเช่น:

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

ลองใช้ดูและดูว่ามันเริ่มมีเหตุผลหรือไม่


1
ตกลงดังนั้นฉันต้องควบคุมรหัสของฉันเพราะไฟล์ json นี้สร้างขึ้นจากวัตถุ java ขอบคุณ
michele

5
ขอบคุณสำหรับการแก้ปัญหา ฉันได้รับสัญลักษณ์ยูนิโค้ดในขณะที่พิมพ์ (เช่น u'valore ') จะป้องกันได้อย่างไร?
Diaryfolio

6
ดีมาก แต่ไพ ธ อนเพิ่มu'คีย์ก่อนหน้าแต่ละคีย์ มีความคิดอะไรบ้าง
CodyBugstein

7
นั่นคือเหตุผลที่ข้อความของคุณพิมพ์ unicode ไม่ใช่ string เวลาส่วนใหญ่จะเป็นการดีที่จะมีข้อความเป็น Unicode สำหรับ umlauts เยอรมันและสำหรับการแบ่งปันผลลัพธ์ข้อความกับโมดูล / โปรแกรมอื่น ๆ ดังนั้นคุณดี!
Michael P

2
ฉันต้องการสังเกตที่หวังว่าจะเป็นประโยชน์และแดกดันแน่นอน ฉันพบว่าโมดูล pprint ด้อยกว่าโมดูล json สำหรับการพิมพ์ที่สวย หากคุณลองทั้งคู่ฉันคิดว่าคุณจะเห็นด้วย ในการแสดงและแก้ไขข้อบกพร่องโครงสร้างข้อมูล json ของฉันฉันได้ทำไปแล้ว: output = json.dumps (data_structure, indent = 2, sort_keys = True) การพิมพ์ (ผลลัพธ์) ฉันคิดว่าคุณจะพบการควบคุมการเยื้องการเรียงลำดับและอัจฉริยะ การพันบรรทัดใน dumps () เป็นวิธีที่คุณชอบ หากความคิดของฉันไม่ถูกต้องใครบางคนโปรดแจ้งให้เราทราบ
Larold

307

คุณdata.jsonควรมีลักษณะเช่นนี้:

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

รหัสของคุณควรเป็น:

import json
from pprint import pprint

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

ทราบว่านี้จะทำงานเฉพาะใน Python 2.6 ขึ้นไปตามที่มันขึ้นอยู่กับ-statementwith ในการใช้ Python 2.5 from __future__ import with_statementใน Python <= 2.4 ดูคำตอบของ Justin Peelซึ่งคำตอบนี้อิง

ตอนนี้คุณสามารถเข้าถึงค่าเดียวเช่นนี้:

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

7
ฉันได้ลงคะแนนในเรื่องนี้ อาจจะไม่ชัดเจนว่าทำไมฉันจึงคิดว่าจำเป็นต้องมีคำตอบอื่น เพิ่มหมายเหตุเกี่ยวกับความเข้ากันได้ของคำสั่ง with
Bengt

ขออภัยสำหรับการย้อนกลับ แต่รหัสที่แนะนำจะทำให้data_file opened นานกว่าที่จำเป็น
Bengt

อ้างถึงเอกสาร 2.6 ( docs.python.org/2.6/library/io.html ) การเปิดไฟล์ในบริบท "with" จะเป็นการปิดไฟล์โดยอัตโนมัติ
Steve S.

1
@SteveS ใช่ แต่ไม่ใช่ก่อนที่บริบทจะถูกทิ้งไว้ pprintไอเอ็นจีใน - withเนื้อหาทำให้data_fileเปิดอีกต่อไป
Bengt

1
@GayanPathirage คุณสามารถเข้าถึงมันเหมือน,data["om_points"] data["masks"]["id"]แนวคิดคือคุณสามารถเข้าถึงทุกระดับในพจนานุกรมโดยระบุ 'เส้นทางที่สำคัญ' หากคุณได้รับKeyErrorข้อยกเว้นหมายความว่าไม่มีคีย์อยู่ในเส้นทาง ระวังคำผิดหรือตรวจสอบโครงสร้างของพจนานุกรมของคุณ
Nuhman

71

คำตอบของ Justin Peelมีประโยชน์จริง ๆ แต่ถ้าคุณใช้ Python 3 อ่าน JSON ควรทำดังนี้:

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

หมายเหตุ: ใช้แทนjson.loads json.loadใน Python 3 json.loadsรับพารามิเตอร์สตริง json.loadใช้พารามิเตอร์วัตถุเหมือนไฟล์ data_file.read()ส่งคืนวัตถุสตริง

พูดตามตรงฉันไม่คิดว่ามันเป็นปัญหาในการโหลดข้อมูล json ทั้งหมดลงในหน่วยความจำส่วนใหญ่


10
เหตุใดจึงควรjson.loadหลีกเลี่ยง.loadsใน Python 3
Zearin

10
loadหน้าเว็บที่คุณเชื่อมโยงไม่ได้พูดอะไรเกี่ยวกับการหลีกเลี่ยง
Dan Hulme

28
คำตอบนี้อ่านไฟล์ทั้งหมดไปยังหน่วยความจำเมื่อไม่จำเป็นและแนะนำว่าในไฟล์ Python 3 JSON ไม่สามารถอ่านได้อย่างขี้เกียจซึ่งไม่จริง ฉันขอโทษ แต่มันชัดเจนว่าเป็นการโหวต
Łukasz Rogalski

10
คำตอบนี้ไม่ถูกต้อง ไม่มีเหตุผลที่จะไม่ใช้ json.load กับตัวจัดการไฟล์แบบเปิดใน python3 ขออภัยสำหรับ downvote แต่ดูเหมือนว่าคุณจะไม่ได้อ่านความคิดเห็นข้างต้นอย่างระมัดระวัง
dusktreader

5
+1 คำตอบนี้ยอดเยี่ยมมาก! ขอบคุณสำหรับสิ่งนั้นและดึงฉันจากการไปไกลเพื่อมองหาฟังก์ชั่นที่สามารถใช้สตริงทำให้ฉันทำงานกับสตริงและคำขอเครือข่ายที่ไม่ใช่ไฟล์เท่านั้น!
ใหม่

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

8
นี่เป็นวิธีแก้ไขที่ถูกต้องหากคุณมีวัตถุ json หลายตัวในไฟล์ json.loadsไม่ถอดรหัสวัตถุ json หลายรายการ มิฉะนั้นคุณจะได้รับข้อผิดพลาด 'ข้อมูลเพิ่มเติม'
yasin_alm

นี่คือคำตอบที่ดีที่สุด มิฉะนั้นจะทำให้เกิดข้อผิดพลาด 'ข้อมูลเพิ่มเติม'
Earthx9

39
การมีหลายวัตถุ json ในไฟล์หมายความว่าไฟล์นั้นไม่ใช่ json ที่ถูกต้องจริง หากคุณมีหลายวัตถุที่จะรวมไว้ในไฟล์ json พวกเขาควรจะอยู่ในอาร์เรย์ที่ระดับบนสุดของไฟล์
dusktreader

การมีวัตถุ json หลายรายการในไฟล์หมายความว่าไฟล์ไม่ใช่วัตถุ json เดียว นั่นเป็นเรื่องที่ชัดเจน การสร้างอาเรย์เดี่ยวออกมาจากวัตถุนั้นเป็นวิธีการแก้ปัญหาที่ชัดเจน แต่ JSON เกิดจากการออกแบบการยกเลิกอย่างชัดเจนเกือบทุกระดับ (โดย}, ]หรือ") ดังนั้นคุณสามารถต่อหลายวัตถุในสตริงเดียวหรือไฟล์เดียวโดยไม่ต้องคลุมเครือ ปัญหาที่นี่คือ parser ที่คาดว่าวัตถุเดียวล้มเหลวเมื่อมันผ่านมากกว่าหนึ่งวัตถุ
MSalters

โฆษณาที่เก็บวัตถุ JSON หลายรายการในไฟล์เดียว: มี "มาตรฐาน" สำหรับสิ่งนั้น - jsonlines.org/examplesใน.jsonl(บรรทัด json) วัตถุจะถูกคั่นด้วยอักขระบรรทัดใหม่ซึ่งทำให้การประมวลผลล่วงหน้าสำหรับการแยกวิเคราะห์เล็กน้อยและอนุญาต เพื่อแยก / แบทช์ไฟล์ได้ง่ายโดยไม่ต้องกังวลกับเครื่องหมายเริ่มต้น / สิ้นสุด
Sebi

13

"Ultra JSON" หรือเพียงแค่ "ujson" สามารถจัดการกับ[]ไฟล์ JSON ของคุณได้ หากคุณกำลังอ่านไฟล์อินพุต JSON ลงในโปรแกรมของคุณเป็นรายการองค์ประกอบ JSON เช่น[{[{}]}, {}, [], etc...]ujson สามารถจัดการรายการคำสั่งใด ๆ ของพจนานุกรมพจนานุกรมรายการ

คุณสามารถค้นหา ujson ในดัชนีแพคเกจ Pythonและ API เกือบจะเหมือนกับjsonห้องสมุดในตัวของ Python

ujson เร็วขึ้นมากเช่นกันถ้าคุณโหลดไฟล์ JSON ที่ใหญ่กว่า คุณสามารถดูรายละเอียดประสิทธิภาพเมื่อเปรียบเทียบกับไลบรารี Python JSON อื่น ๆ ในลิงก์เดียวกันที่มีให้


9

หากคุณใช้ Python3 คุณสามารถลองเปลี่ยน ( connection.jsonไฟล์) JSON เป็น:

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

จากนั้นใช้รหัสต่อไปนี้:

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

1
ยังสามารถใช้งานได้ใน 2.7.5
siddardha

17
เปิดการจัดการไฟล์นี้ออก การใช้withคำสั่งจะดีกว่า
Corey Goldberg

6

ที่นี่คุณไปกับdata.jsonไฟล์แก้ไข:

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

คุณสามารถโทรหรือพิมพ์ข้อมูลบนคอนโซลโดยใช้บรรทัดด้านล่าง:

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

ผลลัพธ์ที่คาดหวังสำหรับprint(data_item['parameters'][0]['id']):

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

ผลลัพธ์ที่คาดหวังสำหรับprint(data_item['parameters'][0]['id']):

valore

หากเราต้องการเพิ่มคอลัมน์เพื่อนับจำนวนการสังเกต "แผนที่" มีเราจะเขียนฟังก์ชั่นนี้ได้อย่างไร?
Chenxi

5

การแยกวิเคราะห์นี้มีสองประเภท

  1. แยกข้อมูลจากไฟล์จากเส้นทางของระบบ
  2. แยก JSON จาก URL ระยะไกล

จากไฟล์คุณสามารถใช้สิ่งต่อไปนี้

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

arcticle นี้อธิบายการแยกวิเคราะห์แบบเต็มและการรับค่าโดยใช้สองสถานการณ์ การแยก JSON โดยใช้ Python


4

ในฐานะผู้ใช้ python3 ,

ความแตกต่างระหว่างloadและloadsวิธีการมีความสำคัญโดยเฉพาะอย่างยิ่งเมื่อคุณอ่านข้อมูล json จากไฟล์

ตามที่ระบุไว้ในเอกสาร:

json.load:

Deserialize fp (.read () - รองรับไฟล์ข้อความหรือไฟล์ไบนารีที่มีเอกสาร JSON) ไปยังวัตถุ Python โดยใช้ตารางการแปลงนี้

json.loads:

json.loads: Deserialize s (อินสแตนซ์ str, bytes หรือ bytearray ที่มีเอกสาร JSON) ไปยังวัตถุ Python โดยใช้ตารางการแปลงนี้

วิธีการ json.load สามารถอ่านเอกสาร json ที่เปิดอยู่ได้โดยตรงเนื่องจากสามารถอ่านไฟล์ไบนารีได้

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

ดังนั้นข้อมูล json ของคุณจึงมีอยู่ในรูปแบบที่ระบุตามตารางการแปลงนี้:

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


นี่เป็นคำตอบของคำถามที่ถามหรือไม่ ผู้ใช้กำลังใช้วิธีการที่ถูกต้องในการโหลดไฟล์ json
Raj006
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.