Python json.loads zeigt ValueError: Zusätzliche Daten

151

Ich erhalte einige Daten aus einer JSON-Datei "new.json" und möchte einige Daten filtern und in einer neuen JSON-Datei speichern. Hier ist mein Code:

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

und ich erhalte eine Fehlermeldung, der Traceback lautet:

  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)

Kann mir jemand helfen?

Hier ist ein Beispiel der Daten in new.json. Die Datei enthält etwa 1500 weitere solcher Wörterbücher

{
    "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
quelle
Dies ist der Fehler, den Sie erhalten, wenn der Eingabe-JSON mehr als ein Objekt pro Zeile enthält. Viele der Antworten hier gehen davon aus, dass es nur ein Objekt pro Zeile gibt, oder konstruieren Beispiele, die dem entsprechen, würden aber brechen, wenn dies nicht der Fall wäre.
smci
@smci: Kannst du die Zeile erklärenmore than one object per line
strebend1

Antworten:

150

Wie Sie im folgenden Beispiel sehen können, dekodiert json.loads(und json.load) nicht mehrere JSON-Objekte.

>>> 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)

Wenn Sie mehrere Wörterbücher sichern möchten, wickeln Sie sie in eine Liste ein und sichern Sie die Liste (anstatt Wörterbücher mehrmals zu sichern).

>>> dict1 = {}
>>> dict2 = {}
>>> json.dumps([dict1, dict2])
'[{}, {}]'
>>> json.loads(json.dumps([dict1, dict2]))
[{}, {}]
falsetru
quelle
7
Können Sie dies bitte noch einmal unter Bezugnahme auf den oben angegebenen Code erklären? Ich bin ein Neuling und manchmal brauche ich lange, um solche Dinge zu verstehen.
Apoorv Ashutosh
1
@ ApoorvAshutosh, Es scheint, als ob es new.jsoneinen JSON und andere redundante Daten enthält. json.load, json.loadsKann nur eine json dekodieren. ValueErrorWie Sie sehen , wird ein erhöht, wenn zusätzliche Daten auftreten.
Falsetru
Ich habe ein Beispiel aus new.json eingefügt und filtere einige Daten daraus heraus, sodass ich nicht weiß, woher ich zusätzliche Daten
erhalte
1
@ ApoorvAshutosh, Sie sagten 1500 weitere solcher Wörterbücher in der bearbeiteten Frage. Das sind die zusätzlichen Daten. Wenn Sie derjenige sind, der einen erstellt hat new.json, fügen Sie einfach einen einzelnen JSON in eine Datei ein.
Falsetru
1
@ApoorvAshutosh, Wenn Sie mehrere Wörterbücher als json ausgeben müssen, schließen Sie sie in eine Liste ein und sichern Sie die Liste.
Falsetru
100

Sie können einfach aus einer Datei jsonifyingjede Zeile lesen, während Sie gehen:

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

Dadurch wird vermieden, dass zwischengeschaltete Python-Objekte gespeichert werden. Solange Sie einen vollständigen Tweet pro append()Anruf schreiben , sollte dies funktionieren.

Adam Hughes
quelle
7
In der akzeptierten Antwort wird beschrieben, wie Sie die Ursache des Problems beheben können, wenn Sie den Exportvorgang steuern. Wenn Sie jedoch die Daten einer anderen Person verwenden und sich nur damit befassen müssen, ist dies eine großartige Methode mit geringem Overhead.
Charlesreid1
3
Viele Datensätze (z. B. Yelp-Dataset) werden heutzutage als "Satz" von Json-Objekten bereitgestellt, und Sie können sie bequem laden.
Gabrer
35

Ich bin darauf gestoßen, weil ich versucht habe, eine aus MongoDB gespeicherte JSON-Datei zu laden. Es gab mir einen Fehler

JSONDecodeError: Extra data: line 2 column 1

Der MongoDB-JSON-Speicherauszug hat ein Objekt pro Zeile. Für mich hat also Folgendes funktioniert:

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

Dies kann auch passieren, wenn Ihre JSON-Datei nicht nur 1 JSON-Datensatz ist. Ein JSON-Datensatz sieht folgendermaßen aus:

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

Es öffnet und schließt mit einer Klammer [], in den Klammern befinden sich die Klammern {}. Es kann viele Klammerpaare geben, aber alles endet mit einer engen Klammer. Wenn Ihre JSON-Datei mehr als eine davon enthält:

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

dann schlägt load () fehl.

Ich habe dies mit meiner eigenen Datei überprüft, die fehlgeschlagen ist.

import json

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

Dies funktioniert, weil 1_guests.json einen Datensatz [] hat. Die ursprüngliche Datei, die ich all_guests.json verwendete, hatte 6 Datensätze, die durch Zeilenumbrüche getrennt waren. Ich habe 5 Datensätze gelöscht (die ich bereits in Klammern überprüft habe) und die Datei unter einem neuen Namen gespeichert. Dann funktionierte die Ladeanweisung.

Fehler war

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

PS. Ich benutze das Wort Datensatz, aber das ist nicht der offizielle Name. Wenn Ihre Datei Zeilenumbrüche wie meine enthält, können Sie sie durchlaufen, um jeweils einen Datensatz in eine JSON-Variable zu laden ().

VISQL
quelle
2
Gibt es eine Möglichkeit, json.loadsdurch Zeilenumbrüche getrennte JSON-Chunks zu lesen? Das heißt, sich so zu verhalten [json.loads(x) for x in text.split('\n')]? Verwandte json.dumpsThemen : Gibt es eine Garantie, die keine wörtlichen Zeilenumbrüche mit Standardeinzug in die Ausgabe einbezieht?
Ben
1
@Ben json.dumpsändert standardmäßig die Zeilenumbrüche im Textinhalt in "\n", sodass Ihr JSON in einer einzelnen Zeile bleibt .
Jchook
7

Nun, es könnte jemandem helfen. Ich habe gerade den gleichen Fehler erhalten, während meine JSON-Datei so ist

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

und ich fand es missgebildet, also habe ich es in eine Art von geändert

{
  "datas":[
    {"id":"1101010","city_id":"1101","name":"TEUPAH SELATAN"},
    {"id":"1101020","city_id":"1101","name":"SIMEULUE TIMUR"}
  ]
}
Akbar Noto
quelle
1
Laden genau wie deine, json.load (infile)
Akbar Noto
6

Einzeiler für Ihr Problem:

data = [json.loads(line) for line in open('tweets.json', 'r')]
Nihal
quelle
1
Dies ist keine allgemeine Lösung. Es wird davon ausgegangen, dass die Eingabe ein JSON-Objekt pro Zeile enthält, und es wird unterbrochen, wenn dies nicht der Fall ist.
smci
3

Wenn Sie es in einem Zweiliner lösen möchten, können Sie es folgendermaßen tun:

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

Ich denke, das Speichern von Diktaten in einer Liste ist keine ideale Lösung, die hier von @falsetru vorgeschlagen wird.

Besser ist es, Dikte zu durchlaufen und sie durch Hinzufügen einer neuen Zeile in .json zu speichern.

Unsere 2 Wörterbücher sind

d1 = {'a':1}

d2 = {'b':2}

Sie können sie an .json schreiben

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

und Sie können json-Datei ohne Probleme lesen

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

einfach und effizient

murat yalçın
quelle
Dies ist keine allgemeine Lösung. Es wird davon ausgegangen, dass die Eingabe ein JSON-Objekt pro Zeile enthält, und es wird unterbrochen, wenn dies nicht der Fall ist.
smci