#arrays #json #azure #azure-logic-apps
#массивы #json #azure #azure-logic-apps
Вопрос:
Я считываю данные из веб-службы, используя вызов API JSON. Он возвращает данные в (ИМХО) необычном формате:
{
"statusCode": 200,
"headers": {
"Transfer-Encoding": "chunked",
"Content-Type": "application/json; charset=UTF-8",
},
"body": {
"columns": {
"column": [
{
"id": -1,
"val": null,
"name": "COLUMNA",
"caption": "Column A",
"value": null
},
{
"id": 106009714,
"val": null,
"name": "COLUMNB",
"caption": "Column B",
"value": null
},
{
"id": 106010949,
"val": null,
"name": "COLUMNC",
"caption": "Column C",
"value": null
},
{
"id": 106009719,
"val": null,
"name": "COLUMND",
"caption": "Column D",
"value": null
},
"records": {
"record": [
{
"field": [
{
"id": -1,
"val": "390011768",
"name": "COLUMNA",
"caption": null,
"value": null
},
{
"id": 106009714,
"val": "Lorem ipsum",
"name": "COLUMNB",
"caption": null,
"value": null
},
{
"id": 106010949,
"val": "Nulla mauris ante",
"name": "COLUMNC",
"caption": null,
"value": null
},
{
"id": 106009719,
"val": "15-01-2019 12:46",
"name": "COLUMND",
"caption": null,
"value": null
}
]
},
{
"field": [
{
"id": -1,
"val": "390012438",
"name": "COLUMNA",
"caption": null,
"value": null
},
{
"id": 106009714,
"val": "Vestibulum ligula",
"name": "COLUMNB",
"caption": null,
"value": null
},
{
"id": 106010949,
"val": "Nulla elit orci",
"name": "COLUMNC",
"caption": null,
"value": null
},
{
"id": 106009719,
"val": "27-03-2019 14:17",
"name": "COLUMND",
"caption": null,
"value": null
}
]
},
{
"field": [
{
"id": -1,
"val": "390013343",
"name": "COLUMNA",
"caption": null,
"value": null
},
{
"id": 106009714,
"val": "Nunc magna risus",
"name": "COLUMNB",
"caption": null,
"value": null
},
{
"id": 106010949,
"val": "Vivamus rutrum",
"name": "COLUMNC",
"caption": null,
"value": null
},
{
"id": 106009719,
"val": "23-07-2019 13:17",
"name": "COLUMND",
"caption": null,
"value": null
}
]
}
]
}
}
}
Первый блок описывает заголовки столбцов, за которым следует другой блок, где каждая строка определяется как массив полей. Моя цель — преобразовать это в следующий (ИМХО) более обычный формат:
{
{
"Column A":"390011768",
"Column B":"Lorem ipsum",
"Column C":"Nulla mauris ante",
"Column D":"27-03-2019 14:17"
},
etc
}
Я придумал решение, но оно кажется беспорядочным / неправильным и включает в себя множество преобразований между объектами strings и массивами. Код для этого приведен ниже:
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"CreateJSON": {
"inputs": {
"body": {
"columns": {
"column": [
{
"caption": "Column A",
"id": -1,
"name": "COLUMNA",
"val": null,
"value": null
},
{
"caption": "Column B",
"id": 106009714,
"name": "COLUMNB",
"val": null,
"value": null
},
{
"caption": "Column C",
"id": 106010949,
"name": "COLUMNC",
"val": null,
"value": null
},
{
"caption": "Column D",
"id": 106009719,
"name": "COLUMND",
"val": null,
"value": null
}
]
},
"records": {
"record": [
{
"field": [
{
"caption": null,
"id": -1,
"name": "COLUMNA",
"val": "390011768",
"value": null
},
{
"caption": null,
"id": 106009714,
"name": "COLUMNB",
"val": "Lorem ipsum",
"value": null
},
{
"caption": null,
"id": 106010949,
"name": "COLUMNC",
"val": "Nulla mauris ante",
"value": null
},
{
"caption": null,
"id": 106009719,
"name": "COLUMND",
"val": "15-01-2019 12:46",
"value": null
}
]
},
{
"field": [
{
"caption": null,
"id": -1,
"name": "COLUMNA",
"val": "390012438",
"value": null
},
{
"caption": null,
"id": 106009714,
"name": "COLUMNB",
"val": "Vestibulum ligula",
"value": null
},
{
"caption": null,
"id": 106010949,
"name": "COLUMNC",
"val": "Nulla elit orci",
"value": null
},
{
"caption": null,
"id": 106009719,
"name": "COLUMND",
"val": "27-03-2019 14:17",
"value": null
}
]
},
{
"field": [
{
"caption": null,
"id": -1,
"name": "COLUMNA",
"val": "390013343",
"value": null
},
{
"caption": null,
"id": 106009714,
"name": "COLUMNB",
"val": "Nunc magna risus",
"value": null
},
{
"caption": null,
"id": 106010949,
"name": "COLUMNC",
"val": "Vivamus rutrum",
"value": null
},
{
"caption": null,
"id": 106009719,
"name": "COLUMND",
"val": "23-07-2019 13:17",
"value": null
}
]
}
]
}
},
"headers": {
"Content-Type": "application/json; charset=UTF-8",
"Date": "Tue, 22 Sep 2020 17:26:18 GMT",
"Transfer-Encoding": "chunked"
},
"statusCode": 200
},
"runAfter": {},
"type": "Compose"
},
"Create_HTML_table": {
"inputs": {
"format": "HTML",
"from": "@variables('RecordArray')"
},
"runAfter": {
"ReconstituteArray": [
"Succeeded"
]
},
"type": "Table"
},
"FlattenArray": {
"inputs": {
"variables": [
{
"name": "ArrayString",
"type": "string",
"value": "@{replace(join(variables('RowAccumulator'), ','),'],[',',')}"
}
]
},
"runAfter": {
"RowLoop": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"HeaderCollection": {
"actions": {
"ColumnHeadings": {
"inputs": {
"caption": "@items('HeaderCollection')['caption']",
"name": "@items('HeaderCollection')['name']"
},
"runAfter": {},
"type": "Compose"
}
},
"foreach": "@outputs('CreateJSON')['body']['columns']['column']",
"runAfter": {
"CreateJSON": [
"Succeeded"
]
},
"type": "Foreach"
},
"InitFieldAccumulator": {
"inputs": {
"variables": [
{
"name": "FieldAccumulator",
"type": "array"
}
]
},
"runAfter": {
"InitRowString": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"InitRowAccumulator": {
"inputs": {
"variables": [
{
"name": "RowAccumulator",
"type": "array"
}
]
},
"runAfter": {
"InitFieldAccumulator": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"InitRowString": {
"inputs": {
"variables": [
{
"name": "RowString",
"type": "string"
}
]
},
"runAfter": {
"HeaderCollection": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"ReconstituteArray": {
"inputs": {
"variables": [
{
"name": "RecordArray",
"type": "array",
"value": "@json(variables('ArrayString'))"
}
]
},
"runAfter": {
"FlattenArray": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"RowLoop": {
"actions": {
"FieldLoop": {
"actions": {
"Compose": {
"inputs": "@setProperty(item(), 'caption', body('MatchCaption')[0]['caption'])",
"runAfter": {
"MatchCaption": [
"Succeeded"
]
},
"type": "Compose"
},
"FieldAccumulator": {
"inputs": {
"name": "FieldAccumulator",
"value": "@outputs('Compose')"
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "AppendToArrayVariable"
},
"MatchCaption": {
"inputs": {
"from": "@outputs('ColumnHeadings')",
"where": "@equals(item()['name'], items('FieldLoop')['name'])"
},
"runAfter": {},
"type": "Query"
}
},
"foreach": "@items('RowLoop')['field']",
"runAfter": {},
"runtimeConfiguration": {
"concurrency": {
"repetitions": 1
}
},
"type": "Foreach"
},
"FlattenRow": {
"inputs": {
"name": "RowString",
"value": "@{replace(string(body('Select')), '},{', ',')}"
},
"runAfter": {
"Select": [
"Succeeded"
]
},
"type": "SetVariable"
},
"Reset_FieldAccumulator": {
"inputs": {
"name": "FieldAccumulator",
"value": []
},
"runAfter": {
"RowAccumulator": [
"Succeeded"
]
},
"type": "SetVariable"
},
"RowAccumulator": {
"inputs": {
"name": "RowAccumulator",
"value": "@variables('RowString')"
},
"runAfter": {
"FlattenRow": [
"Succeeded"
]
},
"type": "AppendToArrayVariable"
},
"Select": {
"inputs": {
"from": "@variables('FieldAccumulator')",
"select": {
"@{item()['caption']}": "@item()['val']"
}
},
"runAfter": {
"FieldLoop": [
"Succeeded"
]
},
"type": "Select"
}
},
"foreach": "@outputs('CreateJSON')['body']['records']['record']",
"runAfter": {
"InitRowAccumulator": [
"Succeeded"
]
},
"runtimeConfiguration": {
"concurrency": {
"repetitions": 1
}
},
"type": "Foreach"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"Recurrence": {
"recurrence": {
"frequency": "Day",
"interval": 1
},
"type": "Recurrence"
}
}
},
"parameters": {}
}
Сначала я создаю полезную нагрузку JSON (имитируя то, что возвращается из API). Затем у меня есть цикл, который создает массив с именами столбцов и заголовками, которые я использую позже для предоставления удобных имен столбцов.
Второй цикл повторяет элементы «записи», которые сами по себе являются массивами. Он использует filterArray для поиска правильного заголовка, использует Compose для создания фрагмента JSON, а затем сохраняет это для каждого поля.
Когда все поля для строки обработаны, я использую Select, чтобы выделить нужные мне значения, а затем преобразовать это в «обычный» элемент JSON и сохранить его.
После обработки всех строк я выполняю еще некоторую обработку, разработанную методом проб и ошибок, чтобы получить что-то, что будет работать с функцией Create HTML Table .
Хотя этот подход работает, он кажется слишком сложным. Однако я не смог найти другого способа сделать это, который сработал. Я новичок в логических приложениях, но не в программировании. Может ли кто-нибудь предложить лучший / более идиоматический способ достижения этой цели? Или этот тип обработки лучше всего передать на аутсорсинг функции?
PS Приложение Logic будет работать с небольшими наборами данных (двузначными числами), поэтому меня не слишком беспокоит производительность, но, по-видимому, более идиоматичное решение будет работать лучше.
Комментарии:
1. В конце преобразования вы просто используете его для создания html, это единственная цель? Происходит ли какая-либо другая обработка, если, возможно, создание html из того, что доступно, было бы намного эффективнее, как вы думаете?
2. @DipenShah Причина, по которой я выбираю вывод HTML и отправляю его по электронной почте, заключается в проверке правильности преобразования. Ключевым элементом здесь является преобразование. Я мог бы в конечном итоге встроить HTML в другую веб-страницу, но мог бы в равной степени проанализировать представление CSV, XML или JSON.
Ответ №1:
Вы можете использовать шаблоны Liquid для определения сложных преобразований json, как это предложено в документах:
Для сложных и сложных преобразований JSON в JSON, содержащих такие элементы, как итерации, потоки управления и переменные, создавайте и используйте шаблоны, описывающие эти преобразования, используя язык шаблонов Liquid с открытым исходным кодом.
Простой способ создания шаблонов liquid — это использование кода Visual Studio с некоторыми плагинами.
Основное преимущество заключается в том, что создание преобразования таким образом намного проще, чем с помощью конструктора приложений Logic. Кроме того, логика преобразования отделена от бизнес-логики.
Вы также можете использовать шаблоны Liquid для преобразования JSON в текст, поэтому преобразование в html напрямую является вариантом.
Кстати, кажется, что ваш входной json неверен, поэтому я не смог привести простой пример.