Python. Json, рекурсия. не могу достичь ключа
Нужно добраться до ключа при помощи рекурсии.
Пожалуйста, прежде чем минусовать, прочтите пункт 3.1
- Дано:
Json, см. ниже
{
"data": [
{
"contents": [
{
"node": "strong",
"contents": [
{
"node": "em",
"text": "some NESTED cool text"
}
],
"startTime": "00.000",
"stopTime": "00.001",
"id": "id_1",
"text": " "
},
{
"contents": [
{
"startTime": "00.000",
"stopTime": "00.001",
"id": "id_2",
"text": "some cool text"
}
]
}
]
}
Необходимо:
2.1. Рекурсией брать из него 2 поля для каждого объекта: "text", "id"
2.2. При условии, если значение "text" - пустая строка, - взять значение ключа "id" с этого уровня, после чего - провалиться на уровень глубже и взять там значение ключа "text"
2.3. Вернуть (вывести и тд) полученный "id" и "text"
Что сделано:
3.1. В этой https://ru.stackoverflow.com/questions/1557996/Рекурсивный-поиск-Нужно-получить-значения-по-двум-ключам моей теме уважаемый insolor, за что ему большое спасибо, частично дал мне ответ но это слегка другая проблема, по этому решил создать новую тему. Собственно, сама рекурсия
def json_find(d, needle):
if isinstance(d, dict):
if needle in d:
yield d[needle], d["id"]
for value in d.values():
yield from json_find(value, needle)
elif isinstance(d, list):
for value in d:
yield from json_find(value, needle)
for text, id_ in json_find(data, "text"):
print(f"id: {id_}, text: {text}")
3.2 Вот такое не работает
import json
# from logic import *
# FILE = get_last_changed_file()
CHAPTERS_KEY = 'chapterId'
FRAMES_KEY = 'frameId'
searched_substr = [' ', ' .', ' ,', ' :', ' ;', '( ', ' )', '{ ', ' }', 'keywords']
with open('../files/fullChapterArrayNEW.json', "r", encoding="utf-8") as f:
data = json.loads(f.read())
def json_find(substr, d, needle):
if isinstance(d, dict):
if needle in d:
if substr in d[needle]:
try:
yield d[needle], d["id"]
except:
yield d[needle], None
for value in d.values():
yield from json_find(substr, value, needle)
elif isinstance(d, list):
for value in d:
yield from json_find(substr, value, needle)
for i in range(len(searched_substr)):
for text, id_ in json_find(searched_substr[i], data, "text"):
print(f"substring: {searched_substr[i]} -//-, id: {id_} -//-, text: {text}")
f.close()
Ответы (1 шт):
Лучше в самой функции поиска ничего не менять (не добавлять какую-то дополнительную сложную логику), пусть она занимается только поиском нужного ключа. Наружу кроме значения ключа и id передаете еще вложенный contents. Все дополнительные проверки делаете снаружи.
Примерный код:
def json_find(d, needle):
if isinstance(d, dict):
if needle in d:
yield d[needle], d.get("id"), d.get("contents") # <-- поменялась только эта строка
for value in d.values():
yield from json_find(value, needle)
elif isinstance(d, list):
for value in d:
yield from json_find(value, needle)
data = {
"data": [
{
"contents": [
{
"node": "strong",
"contents": [{"node": "em", "text": "some NESTED cool text"}],
"startTime": "00.000",
"stopTime": "00.001",
"id": "id_1",
"text": " ",
},
{
"contents": [
{
"node": "strong",
"startTime": "00.000",
"stopTime": "00.001",
"id": "id_2",
"text": "some cool text",
}
]
},
]
}
]
}
for text, id_, contents in json_find(data, "text"):
# print(f"id: {id_}, text: {text}, contents: {contents}")
if text == " " and contents: # Текст равен пустой строке и contents не пустой
# Дальше из contents вытаскиваете то что вам нужно, для примера - содержимое ключа text первого элемента
print(contents[0]["text"])
Вывод:
some NESTED cool text