首页 > 解决方案 > 如何遍历 JSON

问题描述

我目前正在研究一个步行 json,我可以在其中添加参数,在步行中添加我想要通过 JSON 的步行。我创造了这样的东西:

from collections import abc


def walk(obj, *path):
    """
    Goes through the given json path. If it is found then return the given path else empty dict
    """
    for segment in path:
        if not isinstance(obj, abc.Mapping) or segment not in obj:
            print(f"Couldn't walk path; {path}")
            return {}
        obj = obj[segment]
    return obj

# -------------------------------------------------------- #

json_value = {
    "id": "dc932304-dde4-3517-8b76-58081cc9dd0d",
    "Information": [{
        "merch": {
            "id": "8fb66657-b93d-5f2d-8fe7-a5e355f0f3a8",
            "status": "ACTIVE"
        },
        "value": {
            "country": "SE IS BEST"

        },
        "View": {
            "id": "9aae10f4-1b75-481d-ac5f-b17bc46675bd"
        }
    }],
    "collectionTermIds": [

    ],
    "resourceType": "thread",
    "rollup": {
        "totalThreads": 1,
        "threads": [

        ]
    },
    "collectionsv2": {
        "groupedCollectionTermIds": {

        },
        "collectionTermIds": [

        ]
    }
}

# -------------------------------------------------------- #

t = walk(json_value, "Information",  0)
print(t)

我目前的问题是,我试图通过为walk函数提供我提供的值 0 从“信息”中获取列表中的第一个,但是它返回它不能由于Couldn't walk path; ('Information', 0)

我想知道如何通过将其输入参数来选择要遍历的列表编号?例如,如果我选择 1,它应该返回Couldn't walk path; ('Information', 1),但如果我选择这样做0,它应该返回

{
        "merch": {
            "id": "8fb66657-b93d-5f2d-8fe7-a5e355f0f3a8",
            "status": "ACTIVE"
        },
        "value": {
            "country": "SE IS BEST"

        },
        "View": {
            "id": "9aae10f4-1b75-481d-ac5f-b17bc46675bd"
        }
    }

标签: jsonpython-3.x

解决方案


这应该适用于任何 JSON 对象:

def walk(obj, *path):
    """
    Goes through the given json path. If it is found then return the given path else empty dict
    """
    try:
        segment, key, *rest = path
    except ValueError:
        # We are simply passed in a single key, ex. walk(obj, 'my_key')
        key = path[0]
        try:
            return obj[key]
        except KeyError:
            print(f"Couldn't walk path: {key!r}\n"
                  f"  obj={obj!r}\n"
                  "  reason=key missing from object")
            return {}
        except TypeError:
            print(f"Couldn't walk path: {key!r}\n"
                  f"  obj={obj!r}\n"
                  "  reason=object is not a mapping or array type.")
            return {}
        except IndexError as e:
            print(f"Couldn't walk path: {key!r}\n"
                  f"  obj={obj!r}\n"
                  f"  reason={e}")
            return {}

    # This indicates we want to walk down a nested (or deeply nested) path. We
    # can use recursion to solve this case.

    try:
        inner_obj = obj[segment]
    except KeyError:
        print(f"Couldn't walk path: {segment!r} -> {key!r}\n"
              f"  obj={obj!r}\n"
              "  reason=key missing from object")
        return {}
    except IndexError as e:
        print(f"Couldn't walk path: {segment!r} -> {key!r}\n"
              f"  obj={obj!r}\n"
              f"  reason={e}")
        return {}
    else:
        return walk(inner_obj, key, *rest)

这可能会被优化一点,例如通过except稍微修改删除重复的块。

测试代码(使用json_value上面的代码):

t = walk(json_value, 'Information', 1)
assert t == {}

t = walk(json_value, 'Information', 1, 'value', 'country')
assert t == {}

t = walk(json_value, 'Information', 0)
print(t)
# {'merch': {'id': '8fb66657-b93d-5f2d-8fe7-a5e355f0f3a8', 'status': 'ACTIVE'}, 'value': {'country': 'SE IS BEST'}, 'View': {'id': '9aae10f4-1b75-481d-ac5f-b17bc46675bd'}}

t = walk(json_value, 'Information', 0, 'value', 'country')
print(t)
# SE IS BEST

t = walk(json_value, 'collectionsv2', 'collectionTermIds')
print(t)
# []

t = walk(json_value, 'id')
print(t)
# dc932304-dde4-3517-8b76-58081cc9dd0d

t = walk(json_value, 'id', 'test')
assert t == {}
# error: wrong type

推荐阅读