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

і я отримую помилку, зворотний зворот:

  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.loadsjson.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
Чи можете ви поясніть ще раз з посиланням на код, який я дав вище? Я новачок, і часом потрібно довго сприймати такі речі.
Апоорв Ашутош

1
@ApoorvAshutosh, схоже, new.jsonмістить json та інші зайві дані. json.load, json.loadsможе розшифрувати лише json. Він піднімає, ValueErrorколи стикається з додатковими даними, як бачите.
фальцетру

Я вставив зразок з new.json, і я фільтрую з нього деякі дані, тому я не потрапляю, де я отримую додаткові дані
Апоорв Ашутош,

1
@ApoorvAshutosh, Ви відредагували ще 1500 таких словників . Ось додаткові дані. Якщо ви створили new.json, просто покладіть один json у файл.
фальсетру

1
@ApoorvAshutosh, Якщо вам потрібно скинути кілька словників як json, загорніть їх у список та скиньте список.
фальцетру

100

Ви можете просто читати з файлу, jsonifyingкожен рядок, як ви йдете:

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

Це дозволяє уникнути зберігання проміжних об'єктів пітона. Поки ви пишете один повний твіт за append()дзвінок, це має працювати.


7
Прийнята відповідь стосується того, як виправити джерело проблеми, якщо ви керуєте процесом експорту, але якщо ви використовуєте чужі дані і вам просто доведеться боротися з цим, це чудовий метод з низькими накладними витратами.
charlesreid1

3
Багато наборів даних (наприклад: набір даних Yelp) сьогодні надаються як "набір" об'єктів Json, і ваш підхід зручно їх завантажувати.
Габрер

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 записів, розділених новим рядком. Я видалив 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? Тобто діяти як [json.loads(x) for x in text.split('\n')]? Пов’язано: Чи існує гарантія, що json.dumpsне буде включати буквальні нові рядки у висновок із відступом за замовчуванням?
Бен

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)
Акбар Ното

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

Я думаю, що збереження диктів у списку не є ідеальним рішенням, запропонованим @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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.