首页 > 解决方案 > 通过删除包含某些键的对象来过滤 json 文件

问题描述

我在过滤我的 json 文件时遇到了一些麻烦。基本上我有一个 json 文件,其中每一行都是一个不同的 json 对象(我知道这不是正常的有效格式,但这是我必须使用的),我想遍历每一行并检查它是否包含 1 2 个键(例如“名称”或“名字”)。如果 json 对象中存在这两个键中的任何一个,我想保留它。如果没有,我想删除它。所以最后,我将有一个输出 json 文件,其中不包含缺少这些键的对象。

我已经尝试了很多不同的东西,但我似乎无法让它发挥作用,这就是我到目前为止所拥有的:

jsonList = []

with open(filename) as f:
        for json_line in f:
            obj = json.loads(json_line)
            checker(obj)

def checker(obj):
    check = 0
    if ("name" in obj):
        check = 1
    if ("firstname" in obj):
        check = 1
    if (check == 1):
        jsonList.append(obj)

当我尝试打印 jsonList 后它只是给了我一个空 list [],所以我的check变量从未更改为 1 即使我的文件中有 json 对象具有这些键。

我的 json 文件看起来像这样:(注意:不能保证每个对象内的东西数量,所以我不能只检查)

{"name": "name1", "date": "2018-11-13", "age": 32}
{"firstname": "name2", "date": "2019-05-09", "age": 40}
{"date": "2019-11-04", "age": 35}

有人对我能做什么有任何想法吗?或者,如果您知道为什么我在这里尝试的方法不起作用?

标签: pythonjson

解决方案


您的原始代码似乎对我有用。我按原样使用该checker功能,无需修改:

import json
from io import StringIO
from pprint import pprint

jsonList = []

filedata = StringIO("""\
{"name": "name1", "date": "2018-11-13", "age": 32}
{"firstname": "name2", "date": "2019-05-09", "age": 40}
{"date": "2019-11-04", "age": 35}\
""")


def checker(obj):
    check = 0
    if ("name" in obj):
        check = 1
    if ("firstname" in obj):
        check = 1
    if (check == 1):
        jsonList.append(obj)

for json_line in filedata:
    obj = json.loads(json_line)
    checker(obj)

pprint(jsonList)

输出:

[{'age': 32, 'date': '2018-11-13', 'name': 'name1'},
 {'age': 40, 'date': '2019-05-09', 'firstname': 'name2'}]

优化步骤

有几种不同的方法可以优化您的代码,但我建议的最简单方法是set.intersection将一组必需的键与dict对象中的键进行比较。如果有任何匹配,那么我们添加dict对象,因为它是有效的。

jsonList = []
need_one_of_keys = {'name', 'firstname'}

for json_line in filedata:
    obj = json.loads(json_line)
    if need_one_of_keys.intersection(obj):
        jsonList.append(obj)

pprint(jsonList)

值得一提的另一种方法是将 dictin与内置any函数结合使用:

jsonList = []
need_one_of_keys = frozenset(['name', 'firstname'])

for json_line in filedata:
    obj = json.loads(json_line)
    if any(key in obj for key in need_one_of_keys):
        jsonList.append(obj)

pprint(jsonList)

推荐阅读