У меня возникают проблемы с повторением json, содержащего вложенные строки json (с экранированными кавычками).
(Заранее извиняюсь, я новичок и, вероятно, упускаю какую-то важную информацию...)
Собственно у меня несколько вопросов:
1) Как я могу выполнить итерацию (как я пытался сделать ниже с вложенными циклами for) через элементы под «содержимым раздела» раздела «узлы» (! не раздела «имена элементов»!)? Моя проблема заключается в том, что содержимое раздела представляет собой строку с экранированными кавычками, которая сама по себе представляет собой отдельную строку json.
2) Является ли приведенный пример JSON действительным json? Я попробовал несколько валидаторов, и все они, кажется, терпят неудачу, когда в игру вступают экранированные кавычки.
3) Есть ли более разумный метод доступа к определенным элементам вместо простого перебора всего дерева? Я думаю о чем-то, что указывает пары ключ/значение, например:
my_json_obj['sections']['section-id' = 'nodes']['section-content']['occ_id' = '051MZjd97jUdYfSEOG}k10']
Код:
import json
import requests
import pprint
client = requests.session()
header = {'X-CSRF-Token': 'Fetch', 'Accept': 'application/json', 'Content-Type': 'application/json'}
response = client.get('http://xxxxxx.xxx/ProcessManagement/BranchContentSet(BranchId=\'051MZjd97jUdYfX7{dREAm\',SiteId=\'\',SystemRole=\'D\')/$value',auth=('TestUser', 'TestPass'),headers=header)
my_json_obj = response.json()
sections = my_json_obj['sections']
for mysection in sections:
print(mysection['section-id'])
if mysection['section-id'] == 'NODES':
nodes = mysection['section-content'] #nodes seems to be string
for mynode in nodes:
print(mynode) #prints string character by character
Пример JSON:
{
"smud-data-version": "0.1",
"sections": [
{
"section-id": "ELEMENT-NAMES",
"section-content-version": "",
"section-content": "{\"D\":[
{\"occ_id\":\"051MZjd97kcBgtZiEI0IvW\",\"lang\":\"E\",\"name\":\"0TD1 manuell\"},
{\"occ_id\":\"051MZjd97kcBgtZiEH}IvW\",\"lang\":\"E\",\"name\":\"Documentation\"}
]}"
},
{
"section-id": "NODES",
"section-content-version": "1.0",
"section-content": "[
{\"occ_id\":\"051MZjd97jUdYfSEOG}k10\",\"obj_type\":\"ROOT\",\"reference\":\"\",\"deleted\":\"\",\"attributes\":[]},
{\"occ_id\":\"051MZjd97jUdYfSEOH0k10\",\"obj_type\":\"ROOTGRP\",\"reference\":\"\",\"deleted\":\"\",\"attributes\":[]},
{\"occ_id\":\"051MZjd97jcAnKoe03JRRm\",\"obj_type\":\"SCN\",\"reference\":\"\",\"deleted\":\"\",\"attributes\":[
{\"attr_type\":\"NODE_CHANGED_AT\",\"lang\":\"\",\"values\":[\"20190213095843\"]},
{\"attr_type\":\"NODE_CHANGED_BY\",\"lang\":\"\",\"values\":[\"TestUser\"]},
{\"attr_type\":\"TCASSIGNMENTTYPE\",\"lang\":\"\",\"values\":[\"A\"]},
{\"attr_type\":\"DESCRIPTION\",\"lang\":\"E\",\"values\":[\"Scenario\"]}
]}
]"
}
]
}
Фактический результат:
ELEMENT-NAMES
NODES
[
{
"
o
c
c
_
i
d
"
Действительно, это недопустимый JSON. Буквальные символы новой строки внутри строки в кавычках вместо этого должны быть \ns. Однако проще всего просто удалить их.
@Чарльз Даффи Microsoft делает это для некоторых своих API, например, в манифестах обработчиков файлов OneDrive.. Эта документация говорит, что это «из-за ограничений в расширениях надстроек Azure Active Directory эти действия хранятся сериализованными в строку».
@GiacomoAlzetta, ... поэтому они решили превратить свой технический долг в проблему своих конечных пользователей? Типичный.
@Charles Duffy: извините, я добавил буквальные новые строки, чтобы сделать json более читаемым / добавить какой-то отступ, который выделяет структуру (даже если она находится внутри закодированной строки).
@JHM, ааа. Пожалуйста, постарайтесь убедиться, что когда вы включаете данные, они остаются пригодными для использования кем-то, кто проверяет правильность своих ответов, и, по крайней мере, громко отмечайте, когда вы вносите изменения, противоречащие этой цели.






Надеюсь, вы сможете убедить людей, которые генерируют эти данные, починить свой сервер. Тем не менее, решение проблем может выглядеть так:
# instead of using requests.json(), remove literal newlines and then decode ourselves
# ...because the original data has newline literals in positions where they aren't allowed.
my_json_obj = json.loads(response.text.replace('\n', ''))
for section in my_json_obj['sections']:
if section['section-id'] != 'NODES': continue
# doing another json.loads() here so you treat content as an array, not a string
for node in json.loads(section['section-content']):
__import__('pprint').pprint(node)
... правильно испускает в качестве вывода:
{u'attributes': [],
u'deleted': u'',
u'obj_type': u'ROOT',
u'occ_id': u'051MZjd97jUdYfSEOG}k10',
u'reference': u''}
{u'attributes': [],
u'deleted': u'',
u'obj_type': u'ROOTGRP',
u'occ_id': u'051MZjd97jUdYfSEOH0k10',
u'reference': u''}
{u'attributes': [{u'attr_type': u'NODE_CHANGED_AT',
u'lang': u'',
u'values': [u'20190213095843']},
{u'attr_type': u'NODE_CHANGED_BY',
u'lang': u'',
u'values': [u'TestUser']},
{u'attr_type': u'TCASSIGNMENTTYPE',
u'lang': u'',
u'values': [u'A']},
{u'attr_type': u'DESCRIPTION',
u'lang': u'E',
u'values': [u'Scenario']}],
u'deleted': u'',
u'obj_type': u'SCN',
u'occ_id': u'051MZjd97jcAnKoe03JRRm',
u'reference': u''}```
Действительно, похоже, что у
section-contentесть второй/отдельный уровень кодирования JSON — это очень... эээ... действие необычный со стороны людей, которые его создали. Однако декодируйте его с помощьюjson.loads(), и вот вы — нативная структура данных Python.