删除 JSON 对象中的元素

Posted

技术标签:

【中文标题】删除 JSON 对象中的元素【英文标题】:Why do I get an error "'unicode' object does not support item deletion" when trying to delete values from a JSON object? 【发布时间】:2016-08-05 01:15:51 【问题描述】:

我试图遍历一个对象列表,从每个对象中删除一个元素。每个对象都是一个新行。我正在尝试按原样保存新文件,而不包含对象中的元素。我知道这可能是一项简单的任务,但我似乎无法完成这项工作。如果有人可以伸出援助之手,将不胜感激。谢谢。


"business_id": "fNGIbpazjTRdXgwRY_NIXA",
"full_address": "1201 Washington Ave\nCarnegie, PA 15106",
"hours": 
    "Monday": 
        "close": "23:00",
        "open": "11:00"
    ,
    "Tuesday": 
        "close": "23:00",
        "open": "11:00"
    ,
    "Friday": 
        "close": "23:00",
        "open": "11:00"
    ,
    "Wednesday": 
        "close": "23:00",
        "open": "11:00"
    ,
    "Thursday": 
        "close": "23:00",
        "open": "11:00"
    ,
    "Saturday": 
        "close": "23:00",
        "open": "11:00"
    
,
"open": true,
"categories": ["Bars", "American (Traditional)", "Nightlife", "Lounges", "Restaurants"],
"city": "Carnegie",
"review_count": 7,
"name": "Rocky's Lounge",
"neighborhoods": [],
"longitude": -80.0849416,
"state": "PA",
"stars": 4.0,
"latitude": 40.3964688,
"attributes": 
    "Alcohol": "full_bar",
    "Noise Level": "average",
    "Music": 
        "dj": false
    ,
    "Attire": "casual",
    "Ambience": 
        "romantic": false,
        "intimate": false,
        "touristy": false,
        "hipster": false,
        "divey": false,
        "classy": false,
        "trendy": false,
        "upscale": false,
        "casual": false
    ,
    "Good for Kids": true,
    "Wheelchair Accessible": true,
    "Good For Dancing": false,
    "Delivery": false,
    "Dogs Allowed": false,
    "Coat Check": false,
    "Smoking": "no",
    "Accepts Credit Cards": true,
    "Take-out": true,
    "Price Range": 1,
    "Outdoor Seating": false,
    "Takes Reservations": false,
    "Waiter Service": true,
    "Wi-Fi": "free",
    "Caters": false,
    "Good For": 
        "dessert": false,
        "latenight": false,
        "lunch": false,
        "dinner": false,
        "brunch": false,
        "breakfast": false
    ,
    "Parking": 
        "garage": false,
        "street": false,
        "validated": false,
        "lot": true,
        "valet": false
    ,
    "Has TV": true,
    "Good For Groups": true
,
"type": "business"

我需要删除 hours 元素中包含的信息,但信息并不总是相同的。有些包含所有的日子,有些只包含一两天的信息。我尝试使用的代码是 Pyton,我全天都在搜索它以解决我的问题。我对 Python 不是很熟练。任何帮助,将不胜感激。

import json

with open('data.json') as data_file:
data = json.load(data_file)
for element in data: 
        del element['hours']

对不起,只是添加我在运行代码时遇到的错误是 TypeError: 'unicode' 对象不支持删除项目

【问题讨论】:

是否要删除所有小时键和值? (days,close,open) 还是其中的某个字段? 嗨 Ic123,是的,我想删除里面的所有数据,包括小时元素,这样它就不再可见了。我有一个包含 20,000 个对象的列表,每次我需要尝试循环并删除“小时”以及整个文件中此元素内的所有内容时,这些对象都会从新行开始。我需要将结果写入新文件输出吗?还是代码应该编辑当前文件?任何方向将不胜感激。 嗨@Bradley 在您删除@Apero 建议的hour 键后,您需要将结果写入新文件甚至覆盖旧文件。否则您的文件将不会“知道”您的更改 file = open("newfile.json", "w") file.write(data) 这样的事情似乎不起作用。对不起,如果我遇到这个懒惰。我实际上是在尝试修改要在 Pig 中使用的文件,因为我根本无法让大象鸟 jar 文件工作。我只能使用 JSON 文件中的一个缩进来喂猪。我实际上不知道如何使用 Python,但整天都在努力寻找可以用来操作我的 JSON 文件的东西。谢谢@Ic123 【参考方案1】:
with open('writing_file.json', 'w') as w:
    with open('reading_file.json', 'r') as r:
        for line in r:
            element = json.loads(line.strip())
            if 'hours' in element:
                del element['hours']
            w.write(json.dumps(element))

这是我使用的方法..

【讨论】:

请注意,当您从正在迭代的列表中删除一个元素时,这将跳过元素。对此的解决方案是迭代列表的副本或将要保留的元素复制到新列表中。见***.com/q/6260089/470014【参考方案2】:

假设您要覆盖同一个文件:

import json

with open('data.json', 'r') as data_file:
    data = json.load(data_file)

for element in data:
    element.pop('hours', None)

with open('data.json', 'w') as data_file:
    data = json.dump(data, data_file)

dict.pop(<key>, not_found=None) 可能是您要找的,如果我了解您的要求的话。因为它会删除hours 键(如果存在)并且如果不存在也不会失败。

但是我不确定我是否理解为什么 hours 键是否包含某些天会对您产生影响,因为您只是想摆脱整个键/值对,对吧?

现在,如果您真的想使用 del 而不是 pop,那么您可以通过以下方式使您的代码正常工作:

import json

with open('data.json') as data_file:
    data = json.load(data_file)

for element in data:
    if 'hours' in element:
        del element['hours']

with open('data.json', 'w') as data_file:
    data = json.dump(data, data_file)

编辑 因此,如您所见,我添加了将数据写回文件的代码。 如果要将其写入另一个文件,只需在第二个 open 语句中更改文件名即可。

正如您可能已经注意到的那样,我不得不更改缩进,以便在数据清理阶段关闭文件并在最后覆盖。

with 是所谓的上下文管理器,它提供的任何内容(此处为 data_file 文件描述符)在该上下文中可用。这意味着一旦with 块的缩进结束,文件就会关闭,上下文也会结束,文件描述符也会变得无效/过时。

如果不这样做,您将无法以写入模式打开文件并获取要写入的新文件描述符。

我希望它足够清楚......

第二次编辑

这一次,您似乎很清楚需要这样做:

with open('dest_file.json', 'w') as dest_file:
    with open('source_file.json', 'r') as source_file:
        for line in source_file:
            element = json.loads(line.strip())
            if 'hours' in element:
                del element['hours']
            dest_file.write(json.dumps(element))

【讨论】:

您好 Apero,感谢您的快速回复。好的,所以我在一个文件中有一个包含 20,000,000 个对象的列表,如果可能的话,我需要完全删除该元素,以便这些对象不包含任何时间或日期引用。问题是有些对象有几个小时和几天,有些只是空白我已经运行上面的代码来尝试删除它们,但我错过了什么吗?它运行正常,但文件没有改变。我知道我在这里听起来很愚蠢,因为我可能必须将新数据存储并写入另一个文件?再次感谢您的帮助 当然哦,这里我只修改data列表元素,所以是在内存中。你必须在最后用 json.dump 写下来。要么覆盖同一个文件,要么将其写入一个新文件,由您选择。 存储json.dump()的结果是不是一个错误? AFAIK、json.dump() 没有记录的返回值。 您需要它返回什么?它的结果只是它写的文件,不是吗? 嗨,Apero,这更有意义。谢谢你。我收到一个基于“unicode”对象不支持项目删除的错误。 [开发(主)]$ python jsonedit.py Traceback(最近一次调用最后):文件“jsonedit.py”,第 8 行,在 del element['hours'] TypeError: 'unicode' object does not support item删除

以上是关于删除 JSON 对象中的元素的主要内容,如果未能解决你的问题,请参考以下文章

JS中彻底删除json对象组成的数组中的元素

js遍历对象的几种方法以及 删除对象中的某个元素的方法

从对象 JSONB 中的数组中删除元素

从数组中的 JSON 对象中删除属性 [重复]

将 SWIFT 字典替换为 JSON 对象

怎么删除json数据里的元素