【问题标题】:Python json.loads shows ValueError: Extra dataPython json.loads 显示 ValueError: Extra data
【发布时间】:2014-01-30 06:56:16
【问题描述】:

我从 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 : 你能解释一下more than one object per line这一行吗

标签: python json


【解决方案1】:

正如您在以下示例中看到的,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]))
[{}, {}]

【讨论】:

  • 你能参考我上面给出的代码再解释一下吗?我是新手,有时需要很长时间才能掌握这些东西。
  • @ApoorvAshutosh,似乎new.json 包含一个 json 和另一个冗余数据。 json.load, json.loads 只能解码一个 json。如您所见,当遇到其他数据时,它会引发ValueError
  • 已粘贴来自 new.json 的样本,我正在从中过滤掉一些数据,所以我不知道从哪里获取额外数据
  • @ApoorvAshutosh,您在已编辑的问题中说 1500 多个这样的字典。那是额外的数据。如果您是创建 new.json 的人,只需将单个 json 放入文件中即可。
  • @ApoorvAshutosh,如果您需要将多个字典转储为 json,请将它们包装在一个列表中,然后转储该列表。
【解决方案2】:

你可以从文件中读取,jsonifying 每一行:

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

这避免了存储中间 python 对象。只要您在每次append() 调用时写一条完整的推文,这应该可以工作。

【讨论】:

  • 接受的答案解决了如果您控制导出过程如何解决问题的根源,但是如果您使用的是其他人的数据并且您只需要处理它,这是一个很大的低- 开销方法。
  • 现在许多数据集(例如:Yelp 数据集)作为 Json 对象的“集合”提供,您的方法可以方便地加载它们。
  • 这样就完美了,万一出错我们可以用try...except 修改代码!
【解决方案3】:

我遇到这个是因为我试图加载从 MongoDB 转储的 JSON 文件。它给了我一个错误

JSONDecodeError: Extra data: line 2 column 1

MongoDB JSON 转储每行有一个对象,所以对我有用的是:

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

【讨论】:

  • 我仍然得到json.decoder.JSONDecodeError: Extra data: line 1 column 954 (char 953) 这个答案的代码。我的数据文件肯定有不同的问题。
【解决方案4】:

如果您的 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"}]

那么loads()会失败。

我用我自己的失败文件验证了这一点。

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 条记录(我已经检查过它们是否被方括号括起来)并以新名称保存了文件。然后,loads 语句起作用了。

错误是

   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 变量中。

【讨论】:

  • 有没有办法让json.loads 读取换行符分隔的 json 块?也就是说,表现得像[json.loads(x) for x in text.split('\n')]?相关:是否保证json.dumps 不会在其输出中包含带有默认缩进的文字换行符?
  • @Ben,默认情况下json.dumps 会将文本内容中的换行符更改为"\n",将您的json 保留为一行。
【解决方案5】:

当我的 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"}
  ]
}

【讨论】:

  • 加载和你的一样,json.load(infile)
  • 为了记录,如果这是整个JSON文件,那么外部映射是多余的。根can be an array,可让您将第二个 JSON 简化为一个数组。如果您要存储数组数据,则不需要在无用的映射中使用无用的键 - 只需将其放入根数组中
  • @Zoe 哦,这很有趣,你能给我们举个例子吗?
  • 这并不难。只需将两个映射包装在一个数组中:[{"id":"1101010","city_id":"1101","name":"TEUPAH SELATAN"}, {"id":"1101020","city_id":"1101","name":"SIMEULUE TIMUR"}]。解析是一样的,访问是obj[0]obj[1],...(阅读:就像访问一个普通的数组),你得到的对象是相同的。您的答案需要obj["datas"][0],所以它在功能上是相同的
【解决方案6】:

解决您的问题的一条线:

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

【讨论】:

  • 这不是一个通用的解决方案,它假定输入每行有一个 JSON 对象,但它没有破坏它。
【解决方案7】:

如果你想用两行来解决它,你可以这样做:

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

【讨论】:

    【解决方案8】:

    我认为将字典保存在列表中并不是@falsetru 提出的理想解决方案。

    更好的方法是遍历 dicts 并通过添加新行将它们保存到 .json。

    我们的两本词典是

    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 对象,但它没有破坏它。
    【解决方案9】:

    我的 json 文件的格式与问题中的完全一致,但这里的解决方案都没有解决。最后我在另一个 Stackoverflow 线程上找到了解决方法。由于这篇文章是谷歌搜索的第一个链接,所以我把那个答案放在这里,以便以后其他人更容易找到这篇文章。

    正如人们所说,有效的 json 文件需要以“[”开头,“]”在文件末尾。此外,在每个 json 项而不是“}”之后必须有一个“}”。所有括号都没有引号!这段代码只是将格式错误的 json 文件修改为正确的格式。

    https://stackoverflow.com/a/51919788/2772087

    【讨论】:

      【解决方案10】:

      如果您使用文件描述符的read()方法,则错误是由于\nsymbol...所以不要使用readlines()& co绕过问题删除这样的字符!

      import json
      
      path = # contains for example {"c": 4} also on multy-lines
      
      new_d = {'new': 5}
      with open(path, 'r') as fd:
          d_old_str = fd.read().replace('\n', '') # remove all \n
          old_d = json.loads(d_old_str)
      
      # update new_d (python3.9 otherwise new_d.update(old_d))
      new_d |= old_d
                
      with open(path2, 'w') as fd:
          fd.write(json.dumps(new_d)) # save the dictionary to file (in case needed)
      

      ...如果您真的想在这里使用readlines() 替代解决方案

      new_d = {'new': 5}
      with open('some_path', 'r') as fd:
          d_old_str = ''.join(fd.readlines()) # concatenate the lines
          d_old = json.loads(d_old_str)
      
      # then as above
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-06
        • 2014-12-24
        • 1970-01-01
        • 2018-10-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多