получите ключи из вложенного JSON-файла dict без жесткого кода средних ключей

#python #json #python-3.x #dictionary

Вопрос:

Хотите получить данные MetaEntry из словаря, но каждый раз ключи отличаются некоторыми случайными именами.

например: ['Client']

 dictionary = {
    "Tags":[],
    "ObjectId":
    "ab9c6448-85fe-eb11-b563-281878c3a7fe",
    "Client": {
        "MetaData": {
            "MetaEntry": [
                {
                    "Key": "status",
                    "Value": "Active"
                    },
                {
                    "Key": "first_day_of_week",
                    "Value": "Monday"
                    },
                {
                    "Key": "default_induction_expiry",
                    "Value": "0"
                    }
                ]
            },
        "RelatedLinks": [],
        "Tags": [],
        "ObjectId": "6cf54386-d81a-eb11-9fb4-281878b13795",
        "Type": "Artifice.Web.Data.Entities.Client",
        "Name": "Amco Logictics "
        }
    }
 

печать(словарь[‘Клиент’][‘Метаданные’][‘MetaEntry’])

здесь ['Client'] ключ будет меняться случайным образом, поэтому моя вышеприведенная забава с печатью не сработает, есть ли обходной способ получить ключ ['MetaData']['MetaEntry'] без жесткого кодирования ['Client'] ?

Комментарии:

1. посмотрите на путь json — pypi.org/project/jsonpath-ng

Ответ №1:

Если у вас глубоко вложенный словарь, вы можете рекурсивно просмотреть его, чтобы найти все MetaEntry ключи:

 dictionary = {
    "Tags": [],
    "ObjectId": "ab9c6448-85fe-eb11-b563-281878c3a7fe",
    "Client": {
        "MetaData": {
            "MetaEntry": [
                {"Key": "status", "Value": "Active"},
                {"Key": "first_day_of_week", "Value": "Monday"},
                {"Key": "default_induction_expiry", "Value": "0"},
            ]
        },
        "RelatedLinks": [],
        "Tags": [],
        "ObjectId": "6cf54386-d81a-eb11-9fb4-281878b13795",
        "Type": "Artifice.Web.Data.Entities.Client",
        "Name": "Amco Logictics ",
    },
}


def find(d):
    if isinstance(d, dict):
        if "MetaEntry" in d:
            yield d["MetaEntry"]
        else:
            for k, v in d.items():
                yield from find(v)
    elif isinstance(d, list):
        for v in d:
            yield from find(v)


for meta_entry in find(dictionary):
    print(meta_entry)
 

С принтами:

 [
    {"Key": "status", "Value": "Active"},
    {"Key": "first_day_of_week", "Value": "Monday"},
    {"Key": "default_induction_expiry", "Value": "0"},
]
 

ИЗМЕНИТЬ: Для печати текущего пути:

 def find(d, cur_path=None):
    if cur_path is None:
        cur_path = []

    if isinstance(d, dict):
        if "MetaEntry" in d:
            yield d["MetaEntry"], cur_path   ["MetaEntry"]
        else:
            for k, v in d.items():
                yield from find(v, cur_path   [k])
    elif isinstance(d, list):
        for i, v in enumerate(d):
            yield from find(v, cur_path   [i])


for meta_entry, cur_path in find(dictionary):
    print(cur_path)
    print(meta_entry)
 

С принтами:

 ['Client', 'MetaData', 'MetaEntry']

[{'Key': 'status', 'Value': 'Active'}, {'Key': 'first_day_of_week', 'Value': 'Monday'}, {'Key': 'default_induction_expiry', 'Value': '0'}]
 

Комментарии:

1. есть ли способ получить ключи-путь в этой функции , например: словарь[‘Клиент’][‘Метаданные’][‘MetaEntry’]. подобный этому

Ответ №2:

приведенный ниже код будет обрабатывать ситуацию, когда «Клиент» будет заменен другой строкой

 data = {"Tags": [], "ObjectId": "ab9c6448-85fe-eb11-b563-281878c3a7fe", "kkk": {"MetaData": {
    "MetaEntry": [{"Key": "status", "Value": "Active"}, {"Key": "first_day_of_week", "Value": "Monday"},
                  {"Key": "default_induction_expiry", "Value": "0"}]}, "RelatedLinks": [], "Tags": [],
                                                                                                "ObjectId": "6cf54386-d81a-eb11-9fb4-281878b13795",
                                                                                                "Type": "Artifice.Web.Data.Entities.Client",
                                                                                                "Name": "Amco Logictics "}}


for k,v in data.items():
    if isinstance(v,dict) and 'MetaData' in v:
        print(f'{k} points to metadata')
 

выход

 kkk points to metadata