Python json.loads hiển thị ValueError: Dữ liệu bổ sung


151

Tôi đang nhận được một số dữ liệu từ tệp JSON "new.json" và tôi muốn lọc một số dữ liệu và lưu trữ vào tệp JSON mới. Đây là mã của tôi:

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

và tôi đang nhận được một lỗi, truy nguyên là:

  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)

Ai đó có thể giúp tôi?

Đây là một mẫu dữ liệu trong new.json, có thêm khoảng 1500 từ điển như vậy trong tệp

{
    "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
} 

Đây là lỗi bạn gặp bất cứ khi nào JSON đầu vào có nhiều hơn một đối tượng trên mỗi dòng. Nhiều câu trả lời ở đây cho rằng chỉ có một đối tượng trên mỗi dòng hoặc xây dựng các ví dụ tuân theo điều đó, nhưng sẽ phá vỡ nếu đó không phải là trường hợp.
smci

@smci: Bạn có thể giải thích dòng này khôngmore than one object per line
tham

Câu trả lời:


150

Như bạn có thể thấy trong ví dụ sau, json.loads(và json.load) không giải mã được nhiều đối tượng 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)

Nếu bạn muốn kết xuất nhiều từ điển, hãy bọc chúng trong một danh sách, kết xuất danh sách đó (thay vì bỏ từ điển nhiều lần)

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

7
Bạn có thể vui lòng giải thích lại với tham chiếu đến mã tôi đã đưa ra ở trên? Tôi là một người mới, và đôi khi mất nhiều thời gian để nắm bắt những điều như vậy.
Apoorv Ashutosh

1
@ApoorvAshutosh, Có vẻ như new.jsonchứa một json và một dữ liệu dư thừa khác. json.load, json.loadschỉ có thể giải mã một json. Nó đưa ra một ValueErrorkhi nó gặp dữ liệu gây nghiện như bạn thấy.
falsetru

Đã dán một mẫu từ new.json và tôi đang lọc một số dữ liệu từ nó, vì vậy tôi không biết mình đang lấy thêm dữ liệu từ đâu
Apoorv Ashutosh

1
@ApoorvAshutosh, Bạn đã nói thêm 1500 từ điển như vậy trong câu hỏi được chỉnh sửa. Đó là dữ liệu bổ sung. Nếu bạn là người đã tạo ra một new.json, chỉ cần đặt một json duy nhất vào một tệp.
falsetru

1
@ApoorvAshutosh, Nếu bạn cần kết xuất nhiều từ điển thành json, hãy bọc chúng trong một danh sách và kết xuất danh sách.
falsetru

100

Bạn chỉ có thể đọc từ một tệp, jsonifyingmỗi dòng khi bạn đi:

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

Điều này tránh lưu trữ các đối tượng trăn trung gian. Miễn là bạn viết một tweet đầy đủ cho mỗi append()cuộc gọi, điều này sẽ hoạt động.


7
Câu trả lời được chấp nhận giải quyết cách khắc phục nguồn gốc của vấn đề nếu bạn kiểm soát quá trình xuất, nhưng nếu bạn đang sử dụng dữ liệu của người khác và bạn chỉ phải xử lý thì đây là một phương pháp chi phí thấp tuyệt vời.
charlesreid1

3
Nhiều bộ dữ liệu (ví dụ: bộ dữ liệu Yelp) hiện nay được cung cấp dưới dạng "bộ" các đối tượng Json và cách tiếp cận của bạn thật tiện lợi khi tải chúng.
Gabrer

36

Tôi đã gặp phải điều này bởi vì tôi đang cố tải một tệp JSON được kết xuất từ ​​MongoDB. Nó đã cho tôi một lỗi

JSONDecodeError: Extra data: line 2 column 1

Kết xuất JSON MongoDB có một đối tượng trên mỗi dòng, vì vậy, điều làm việc cho tôi là:

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

13

Điều này cũng có thể xảy ra nếu tệp JSON của bạn không chỉ là 1 bản ghi JSON. Một bản ghi JSON trông như thế này:

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

Nó mở và đóng bằng dấu ngoặc [], trong dấu ngoặc là dấu ngoặc {}. Có thể có nhiều cặp niềng răng, nhưng tất cả đều kết thúc bằng một dấu ngoặc gần]. Nếu tệp json của bạn chứa nhiều hơn một trong số đó:

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

sau đó tải () sẽ thất bại.

Tôi đã xác minh điều này với tập tin của riêng tôi đã thất bại.

import json

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

Điều này hoạt động vì 1_guests.json có một bản ghi []. Tệp gốc tôi đang sử dụng all_guests.json có 6 bản ghi được phân tách bằng dòng mới. Tôi đã xóa 5 bản ghi, (mà tôi đã kiểm tra để được hỗ trợ bởi dấu ngoặc) và lưu tệp dưới một tên mới. Sau đó, báo cáo tải làm việc.

Lỗi là

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

Tái bút Tôi sử dụng bản ghi từ, nhưng đó không phải là tên chính thức. Ngoài ra, nếu tệp của bạn có các ký tự dòng mới như của tôi, bạn có thể lặp qua nó để tải () một bản ghi tại một thời điểm vào một biến json.


2
Có cách nào json.loadsđể đọc các đoạn json phân định dòng mới không? Đó là, hành động như thế [json.loads(x) for x in text.split('\n')]nào? Liên quan: Có đảm bảo json.dumpssẽ không bao gồm các dòng mới theo nghĩa đen trong đầu ra của nó với thụt lề mặc định?
Bến

1
@Ben, theo mặc định json.dumpssẽ thay đổi dòng mới trong nội dung văn bản thành "\n", giữ json của bạn thành một dòng duy nhất.
jchook

7

Vâng, nó có thể giúp ai đó. tôi chỉ gặp lỗi tương tự trong khi tập tin json của tôi là như thế này

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

và tôi thấy nó không đúng định dạng, vì vậy tôi đã thay đổi nó thành một số

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

1
tải giống như của bạn, json.load (infile)
Akbar Noto

6

Một lớp lót cho vấn đề của bạn:

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

1
Đây không phải là một giải pháp chung, nó giả sử đầu vào có một đối tượng JSON trên mỗi dòng và phá vỡ nó không có.
smci

3

Nếu bạn muốn giải quyết nó trong một hai lớp, bạn có thể làm như thế này:

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

1

Tôi nghĩ rằng lưu dicts trong một danh sách không phải là một giải pháp lý tưởng ở đây được đề xuất bởi @falsetru.

Cách tốt hơn là, lặp lại thông qua các lệnh và lưu chúng vào .json bằng cách thêm một dòng mới.

2 từ điển của chúng tôi là

d1 = {'a':1}

d2 = {'b':2}

bạn có thể viết chúng cho .json

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

và bạn có thể đọc tệp json mà không có bất kỳ vấn đề

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

đơn giản và hiệu quả


Đây không phải là một giải pháp chung, nó giả sử đầu vào có một đối tượng JSON trên mỗi dòng và phá vỡ nó không có.
smci
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.