Python json.loads menunjukkan ValueError: Data ekstra

151

Saya mendapatkan beberapa data dari file JSON "new.json", dan saya ingin memfilter beberapa data dan menyimpannya ke file JSON baru. Ini kode saya:

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

dan saya mendapatkan kesalahan, traceback adalah:

  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)

Adakah yang bisa membantu saya?

Berikut adalah contoh data di new.json, ada sekitar 1500 lebih kamus seperti itu di file

{
    "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
} 
Apoorv Ashutosh
sumber
Ini adalah kesalahan yang Anda dapatkan setiap kali input JSON memiliki lebih dari satu objek per baris. Banyak jawaban di sini menganggap hanya ada satu objek per baris, atau membuat contoh yang mematuhi itu, tetapi akan pecah jika bukan itu masalahnya.
smci
@smci: Bisakah Anda menjelaskan kalimatnyamore than one object per line
aspiring1

Jawaban:

150

Seperti yang Anda lihat pada contoh berikut, json.loads(dan json.load) tidak mendekode beberapa objek 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)

Jika Anda ingin membuang beberapa kamus, bungkus dalam daftar, buang daftar (alih-alih membuang kamus beberapa kali)

>>> dict1 = {}
>>> dict2 = {}
>>> json.dumps([dict1, dict2])
'[{}, {}]'
>>> json.loads(json.dumps([dict1, dict2]))
[{}, {}]
falsetru
sumber
7
Bisakah Anda jelaskan lagi dengan merujuk pada kode yang saya berikan di atas? Saya seorang pemula, dan terkadang butuh waktu lama untuk memahami hal-hal seperti itu.
Apoorv Ashutosh
1
@ApoorvAshutosh, Sepertinya new.jsonberisi json dan data lain yang berlebihan. json.load, json.loadshanya dapat memecahkan kode json. Itu meningkatkan ValueErrorketika menemukan data tambahan seperti yang Anda lihat.
falsetru
Telah menempelkan sampel dari new.json, dan saya memfilter beberapa data dari itu, jadi saya tidak mendapatkan di mana saya mendapatkan data tambahan dari
Apoorv Ashutosh
1
@ApoorvAshutosh, Anda mengatakan 1500 lebih kamus seperti itu dalam pertanyaan yang diedit. Itu adalah data tambahan. Jika Anda yang membuat new.json, cukup masukkan satu json di file.
falsetru
1
@ ApoorvAshutosh, Jika Anda perlu membuang beberapa kamus sebagai json, bungkus dalam daftar, dan buang daftar.
falsetru
100

Anda bisa membaca dari sebuah file, jsonifyingsetiap baris sambil berjalan:

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

Ini menghindari menyimpan objek python perantara. Selama Anda menulis satu tweet penuh per append()panggilan, ini akan berfungsi.

Adam Hughes
sumber
7
Jawaban yang diterima membahas cara memperbaiki sumber masalah jika Anda mengontrol proses ekspor, tetapi jika Anda menggunakan data orang lain dan Anda hanya perlu mengatasinya, ini adalah metode overhead rendah yang bagus.
charlesreid1
3
Banyak dataset (misalnya: Yelp dataset) saat ini disediakan sebagai "set" objek Json dan pendekatan Anda lebih mudah memuatnya.
Gabrer
36

Saya menemukan ini karena saya mencoba memuat file JSON yang dibuang dari MongoDB. Itu memberi saya kesalahan

JSONDecodeError: Extra data: line 2 column 1

Dump MongoDB JSON memiliki satu objek per baris, jadi yang berhasil bagi saya adalah:

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

Ini juga dapat terjadi jika file JSON Anda bukan hanya 1 catatan JSON. Catatan JSON terlihat seperti ini:

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

Ini membuka dan menutup dengan braket [], di dalam kurung ada kurung {}. Mungkin ada banyak pasang kawat gigi, tetapi semuanya berakhir dengan braket yang dekat]. Jika file json Anda mengandung lebih dari satu di antaranya:

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

lalu memuat () akan gagal.

Saya memverifikasi ini dengan file saya sendiri yang gagal.

import json

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

Ini berfungsi karena 1_guests.json memiliki satu catatan []. File asli yang saya gunakan all_guests.json memiliki 6 catatan yang dipisahkan oleh baris baru. Saya menghapus 5 catatan, (yang sudah saya periksa untuk disimpan dengan tanda kurung) dan menyimpan file dengan nama baru. Kemudian pernyataan beban bekerja.

Kesalahan tadinya

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

PS. Saya menggunakan catatan kata, tapi itu bukan nama resmi. Selain itu, jika file Anda memiliki karakter baris baru seperti milik saya, Anda dapat memutarnya untuk memuat () satu catatan sekaligus ke dalam variabel json.

VISQL
sumber
2
Apakah ada cara untuk bisa json.loadsmembaca json chunks dibatasi-baris baru? Yaitu, untuk bertindak seperti [json.loads(x) for x in text.split('\n')]? Terkait: Apakah ada jaminan yang json.dumpstidak akan menyertakan baris baru literal dalam outputnya dengan indentasi default?
Ben
1
@Ben, secara default json.dumpsakan mengubah baris baru dalam konten teks ke "\n", menjaga json Anda ke satu baris.
jchook
7

Yah, itu mungkin membantu seseorang. saya baru saja mendapatkan kesalahan yang sama ketika file json saya seperti ini

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

dan saya menemukan itu cacat, jadi saya mengubahnya menjadi sesuatu dari

{
  "datas":[
    {"id":"1101010","city_id":"1101","name":"TEUPAH SELATAN"},
    {"id":"1101020","city_id":"1101","name":"SIMEULUE TIMUR"}
  ]
}
Akbar Noto
sumber
1
memuat sama seperti milik Anda, json.load (infile)
Akbar Noto
6

Satu-liner untuk masalah Anda:

data = [json.loads(line) for line in open('tweets.json', 'r')]
Nihal
sumber
1
Ini bukan solusi umum, itu mengasumsikan input memiliki satu objek JSON per baris, dan istirahat itu tidak.
smci
3

Jika Anda ingin menyelesaikannya dalam dua baris, Anda dapat melakukannya seperti ini:

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

Saya pikir menyimpan dikte dalam daftar bukan solusi ideal di sini yang diusulkan oleh @ falsetru.

Cara yang lebih baik adalah, beralih melalui dikte dan menyimpannya ke .json dengan menambahkan baris baru.

2 kamus kami adalah

d1 = {'a':1}

d2 = {'b':2}

Anda dapat menulisnya ke .json

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

dan Anda dapat membaca file json tanpa masalah

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

sederhana dan efisien

murat yalçın
sumber
Ini bukan solusi umum, itu mengasumsikan input memiliki satu objek JSON per baris, dan istirahat itu tidak.
smci