Python json.loads แสดง ValueError: ข้อมูลเพิ่มเติม


151

ฉันได้รับข้อมูลบางอย่างจากไฟล์ JSON "new.json" และฉันต้องการกรองข้อมูลบางส่วนและเก็บไว้ในไฟล์ JSON ใหม่ นี่คือรหัสของฉัน:

import json
with open('new.json') as infile:
    data = json.load(infile)
for item in data:
    iden = item.get["id"]
    a = item.get["a"]
    b = item.get["b"]
    c = item.get["c"]
    if c == 'XYZ' or  "XYZ" in data["text"]:
        filename = 'abc.json'
    try:
        outfile = open(filename,'ab')
    except:
        outfile = open(filename,'wb')
    obj_json={}
    obj_json["ID"] = iden
    obj_json["VAL_A"] = a
    obj_json["VAL_B"] = b

และฉันได้รับข้อผิดพลาด traceback คือ:

  File "rtfav.py", line 3, in <module>
    data = json.load(infile)
  File "/usr/lib64/python2.7/json/__init__.py", line 278, in load
    **kw)
  File "/usr/lib64/python2.7/json/__init__.py", line 326, in loads
    return _default_decoder.decode(s)
  File "/usr/lib64/python2.7/json/decoder.py", line 369, in decode
    raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 88 column 2 - line 50607 column 2 (char 3077 - 1868399)

มีคนช่วยฉันได้ไหม

นี่คือตัวอย่างของข้อมูลใน new.json มีพจนานุกรมมากกว่า 1500 รายการในไฟล์

{
    "contributors": null, 
    "truncated": false, 
    "text": "@HomeShop18 #DreamJob to professional rafter", 
    "in_reply_to_status_id": null, 
    "id": 421584490452893696, 
    "favorite_count": 0, 
    "source": "<a href=\"https://mobile.twitter.com\" rel=\"nofollow\">Mobile Web (M2)</a>", 
    "retweeted": false, 
    "coordinates": null, 
    "entities": {
        "symbols": [], 
        "user_mentions": [
            {
                "id": 183093247, 
                "indices": [
                    0, 
                    11
                ], 
                "id_str": "183093247", 
                "screen_name": "HomeShop18", 
                "name": "HomeShop18"
            }
        ], 
        "hashtags": [
            {
                "indices": [
                    12, 
                    21
                ], 
                "text": "DreamJob"
            }
        ], 
        "urls": []
    }, 
    "in_reply_to_screen_name": "HomeShop18", 
    "id_str": "421584490452893696", 
    "retweet_count": 0, 
    "in_reply_to_user_id": 183093247, 
    "favorited": false, 
    "user": {
        "follow_request_sent": null, 
        "profile_use_background_image": true, 
        "default_profile_image": false, 
        "id": 2254546045, 
        "verified": false, 
        "profile_image_url_https": "https://pbs.twimg.com/profile_images/413952088880594944/rcdr59OY_normal.jpeg", 
        "profile_sidebar_fill_color": "171106", 
        "profile_text_color": "8A7302", 
        "followers_count": 87, 
        "profile_sidebar_border_color": "BCB302", 
        "id_str": "2254546045", 
        "profile_background_color": "0F0A02", 
        "listed_count": 1, 
        "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png", 
        "utc_offset": null, 
        "statuses_count": 9793, 
        "description": "Rafter. Rafting is what I do. Me aur mera Tablet.  Technocrat of Future", 
        "friends_count": 231, 
        "location": "", 
        "profile_link_color": "473623", 
        "profile_image_url": "http://pbs.twimg.com/profile_images/413952088880594944/rcdr59OY_normal.jpeg", 
        "following": null, 
        "geo_enabled": false, 
        "profile_banner_url": "https://pbs.twimg.com/profile_banners/2254546045/1388065343", 
        "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png", 
        "name": "Jayy", 
        "lang": "en", 
        "profile_background_tile": false, 
        "favourites_count": 41, 
        "screen_name": "JzayyPsingh", 
        "notifications": null, 
        "url": null, 
        "created_at": "Fri Dec 20 05:46:00 +0000 2013", 
        "contributors_enabled": false, 
        "time_zone": null, 
        "protected": false, 
        "default_profile": false, 
        "is_translator": false
    }, 
    "geo": null, 
    "in_reply_to_user_id_str": "183093247", 
    "lang": "en", 
    "created_at": "Fri Jan 10 10:09:09 +0000 2014", 
    "filter_level": "medium", 
    "in_reply_to_status_id_str": null, 
    "place": null
} 

นี่เป็นข้อผิดพลาดที่คุณได้รับเมื่อใดก็ตามที่อินพุต JSON มีวัตถุมากกว่าหนึ่งรายการต่อบรรทัด คำตอบหลายข้อในที่นี้ถือว่ามีเพียงวัตถุเดียวต่อบรรทัดหรือสร้างตัวอย่างที่เชื่อฟัง แต่จะแตกถ้าไม่ใช่กรณี
smci

@smci: คุณสามารถอธิบายบรรทัดmore than one object per line
aspiring1

คำตอบ:


150

ดังที่คุณเห็นในตัวอย่างต่อไปนี้json.loads(และjson.load) ไม่ถอดรหัสวัตถุ json หลายรายการ

>>> json.loads('{}')
{}
>>> json.loads('{}{}') # == json.loads(json.dumps({}) + json.dumps({}))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\json\__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "C:\Python27\lib\json\decoder.py", line 368, in decode
    raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 1 column 3 - line 1 column 5 (char 2 - 4)

หากคุณต้องการถ่ายโอนพจนานุกรมหลายรายการให้ตัดรายการเหล่านั้นในรายการถ่ายโอนข้อมูลรายการ (แทนที่จะทิ้งพจนานุกรมหลายครั้ง)

>>> dict1 = {}
>>> dict2 = {}
>>> json.dumps([dict1, dict2])
'[{}, {}]'
>>> json.loads(json.dumps([dict1, dict2]))
[{}, {}]

7
คุณช่วยอธิบายอีกครั้งโดยอ้างอิงกับรหัสที่ฉันให้ไว้ข้างต้นได้ไหม ฉันเป็นมือใหม่และบางครั้งก็ใช้เวลานานกว่าจะเข้าใจสิ่งต่าง ๆ
Apoorv Ashutosh

1
@ApoorvAshutosh ดูเหมือนว่าจะnew.jsonมี json และข้อมูลซ้ำซ้อนอื่น json.load, json.loadsสามารถถอดรหัส JSON มันเพิ่มValueErrorเมื่อพบข้อมูลเพิ่มเติมตามที่คุณเห็น
falsetru

วางตัวอย่างจาก new.json แล้วและฉันกำลังกรองข้อมูลบางส่วนออกจากนั้นฉันจึงไม่ได้รับข้อมูลเพิ่มเติมจากที่ใด
Apoorv Ashutosh

1
@ApoorvAshutosh คุณพูดอีก 1,500 พจนานุกรมในคำถามที่แก้ไข นั่นคือข้อมูลเพิ่มเติม หากคุณเป็นผู้สร้างnew.jsonเพียงใส่ json หนึ่งไฟล์
falsetru

1
@ApoorvAshutosh, หากคุณต้องการดัมพ์หลายพจนานุกรมเป็น json, ให้พันคำเหล่านั้นไว้ในรายการและดัมพ์รายการ
falsetru

100

คุณสามารถอ่านจากไฟล์jsonifyingแต่ละบรรทัดในขณะที่คุณไป:

tweets = []
for line in open('tweets.json', 'r'):
    tweets.append(json.loads(line))

วิธีนี้หลีกเลี่ยงการเก็บวัตถุหลามกลาง ตราบใดที่คุณเขียนทวีตเต็มหนึ่งครั้งต่อการappend()โทรข้อความนี้จะใช้ได้


7
คำตอบที่ได้รับการยอมรับจะระบุวิธีแก้ไขแหล่งที่มาของปัญหาหากคุณควบคุมกระบวนการส่งออก แต่ถ้าคุณใช้ข้อมูลของคนอื่นและคุณต้องจัดการกับปัญหานี่เป็นวิธีการที่ค่าใช้จ่ายต่ำมาก
charlesreid1

3
ชุดข้อมูลจำนวนมาก (เช่น: ชุดข้อมูล Yelp) ในปัจจุบันมีให้เป็น "ชุด" ของวัตถุ Json และวิธีการของคุณมันสะดวกในการโหลด
Gabrer

36

ฉันเจอสิ่งนี้เพราะฉันพยายามโหลดไฟล์ JSON ที่ถูกทิ้งจาก MongoDB มันทำให้ฉันมีข้อผิดพลาด

JSONDecodeError: Extra data: line 2 column 1

การถ่ายโอนข้อมูล MongoDB JSON มีหนึ่งวัตถุต่อบรรทัดดังนั้นสิ่งที่ทำงานสำหรับฉันคือ:

import json
data = [json.loads(line) for line in open('data.json', 'r')]

13

สิ่งนี้อาจเกิดขึ้นได้หากไฟล์ JSON ของคุณไม่ใช่เพียง 1 ระเบียน JSON ระเบียน JSON มีลักษณะดังนี้:

[{"some data": value, "next key": "another value"}]

มันเปิดและปิดด้วยวงเล็บ [] ภายในวงเล็บคือวงเล็บปีกกา {} อาจมีวงเล็บปีกกาหลายคู่ แต่ทุกอย่างจบลงด้วยวงเล็บปิด] หากไฟล์ json ของคุณมีมากกว่าหนึ่งไฟล์:

[{"some data": value, "next key": "another value"}]
[{"2nd record data": value, "2nd record key": "another value"}]

จากนั้นโหลด () จะล้มเหลว

ฉันตรวจสอบสิ่งนี้ด้วยไฟล์ของตัวเองที่ล้มเหลว

import json

guestFile = open("1_guests.json",'r')
guestData = guestFile.read()
guestFile.close()
gdfJson = json.loads(guestData)

ใช้งานได้เพราะ 1_guests.json มีหนึ่งระเบียน [] ไฟล์ต้นฉบับที่ฉันใช้ all_guests.json มี 6 รายการคั่นด้วย newline ฉันลบ 5 รายการ (ซึ่งฉันได้ตรวจสอบแล้วว่าได้รับการบันทึกโดยวงเล็บ) และบันทึกไฟล์ภายใต้ชื่อใหม่ จากนั้นคำสั่งโหลดทำงาน

ข้อผิดพลาดคือ

   raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 2 column 1 - line 10 column 1 (char 261900 - 6964758)

PS ฉันใช้บันทึกคำ แต่นั่นไม่ใช่ชื่ออย่างเป็นทางการ นอกจากนี้หากไฟล์ของคุณมีอักขระขึ้นบรรทัดใหม่เช่นของฉันคุณสามารถวนซ้ำเพื่อโหลด () ทีละรายการในตัวแปร json


2
มีวิธีjson.loadsอ่าน json chunks ที่ขึ้นบรรทัดใหม่หรือไม่ นั่นคือเพื่อทำหน้าที่เหมือน[json.loads(x) for x in text.split('\n')]? ที่เกี่ยวข้อง: มีการรับประกันที่json.dumpsจะไม่รวมบรรทัดใหม่ตามตัวอักษรในผลลัพธ์ด้วยการเยื้องเริ่มต้นหรือไม่
Ben

1
@Ben โดยค่าเริ่มต้นjson.dumpsจะเปลี่ยนบรรทัดใหม่ในเนื้อหาข้อความเป็น"\n"ทำให้ json ของคุณเป็นบรรทัดเดียว
jchook

7

มันอาจช่วยใครซักคน ฉันเพิ่งได้รับข้อผิดพลาดเดียวกันในขณะที่ไฟล์ json ของฉันเป็นเช่นนี้

{"id":"1101010","city_id":"1101","name":"TEUPAH SELATAN"}
{"id":"1101020","city_id":"1101","name":"SIMEULUE TIMUR"}

และฉันพบว่ามันมีรูปแบบไม่ถูกต้องดังนั้นฉันจึงเปลี่ยนมันเป็นบางส่วนของ

{
  "datas":[
    {"id":"1101010","city_id":"1101","name":"TEUPAH SELATAN"},
    {"id":"1101020","city_id":"1101","name":"SIMEULUE TIMUR"}
  ]
}

1
กำลังโหลดเช่นเดียวกับคุณ json.load (infile)
Akbar Noto

6

หนึ่งซับสำหรับปัญหาของคุณ:

data = [json.loads(line) for line in open('tweets.json', 'r')]

1
นี่ไม่ใช่วิธีแก้ไขปัญหาทั่วไปโดยสมมติว่าอินพุตมีวัตถุ JSON หนึ่งรายการต่อบรรทัดและแยกมันไม่ได้
smci

3

หากคุณต้องการแก้มันด้วยสองซับคุณสามารถทำสิ่งนี้ได้:

with open('data.json') as f:
    data = [json.loads(line) for line in f]

1

ฉันคิดว่าการบันทึก dicts ในรายการไม่ใช่โซลูชันที่สมบูรณ์แบบที่เสนอโดย @falsetru

วิธีที่ดีกว่าคือวนซ้ำและบันทึกลงใน. json โดยเพิ่มบรรทัดใหม่

พจนานุกรม 2 เล่มของเราคือ

d1 = {'a':1}

d2 = {'b':2}

คุณสามารถเขียนลงใน. json

import json
with open('sample.json','a') as sample:
    for dict in [d1,d2]:
        sample.write('{}\n'.format(json.dumps(dict)))

และคุณสามารถอ่านไฟล์ json ได้โดยไม่มีปัญหาใด ๆ

with open('sample.json','r') as sample:
    for line in sample:
        line = json.loads(line.strip())

ง่ายและมีประสิทธิภาพ


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