Решение этой задачи удобно реализовать при помощи компонента JavaScript. Создадим узел, перетащив компонент JavaScript из палитры инструментов на рабочую область сценария. В табличном входном порту определим поле txtJSON, принимающее текст JSON:
Во входном порту переменных создадим переменную JSON с текстовым типом данных:
Такой узел сможет принимать входные данные с текстом JSON как на табличный входной порт, так и на порт переменных.
Если структура JSON заранее не известна, то в выходном наборе узла JavaScript она может быть представлена в формате key-value. Зададим ее в настройке выходной таблицы:
В выходном наборе поле кеу содержит ключ элемента JSON, а value - его значение. Дополнительные поля: id (индекс строки входного набора, содержащей JSON), parent (путь к элементу в иерархии JSON), type (тип данных элемента). В редакторе кода узла создается следующий скрипт:
import {InputTable, InputVariables, OutputTable} from "builtIn/Data";
let txtJSON;
let obj;
// Проверяем наличие данных во входной наборе.
// Если табличный порт задействован, то обрабатываем данные этого порта.
// В противном случае обрабатываем данные порта входных переменных.
if (InputTable){
for (let j=0, c = InputTable.RowCount; j < c; j++){ // Цикл по строкам входного набора.
txtJSON = InputTable.Get(j, 'txtJSON'); // Переменная txtJSON принимает текст JSON из поля 'txtJSON' входного набора.
obj = JSON.parse(txtJSON); // Переменная obj принимает объект JSON
get_elements(j, obj); // и далее передается в функцию обработки объекта JSON 'get_elements(id, o, p = 'root')'.
}
}else{
console.log("Табличный порт не задействован");
txtJSON = InputVariables.Items.JSON.Value; // Переменная txtJSON принимает текст JSON из переменной 'JSON' входного порта.
if (txtJSON){ // Если txtJSON содержит значение,
obj = JSON.parse(txtJSON); // то obj принимает объект JSON
get_elements('Порт переменных', obj); // и далее передается в функцию обработки объекта JSON.
}else{console.log('Переменная <JSON> входного порта не задана')}
}
// Функция обработки объекта JSON.
// Принимает параметры:
// id - идентификатор строки входного набора;
// o - объект JSON;
// p - parent элемента JSON (по умолчанию = 'root').
function get_elements(id, o, p = 'root') {
let i;
for (let k in o) { // Цикл по элементам JSON.
i = o[k]; // Переменная i принимает текущий элемент JSON.
if (typeof i != 'object') { // Если элемент не имеет подчиненных,
append(id, p, k, typeof i, i); // то просто выводиться в выходной набор данных функцией 'append(id, parent, key, type, value)'.
} else { // В противном случае:
append(id, p, k, typeof i); // выводится в выходной набор
get_elements(id, i, p + ':' + k); // и передается на обработку подчиненных элементов рекурсивным вызовом данной функции.
}
}
}
// Функция вывода элемента JSON в выходной набор данных.
// Принимает параметры:
// id - идентификатор строки входного набора;
// parent - parent элемента JSON;
// key - идентификатор элемента JSON;
// type - тип элемента JSON;
// value - значение элемента JSON.
function append(id, parent = null, key = null, type = null, value = null) {
OutputTable.Append(); // Добавление новой строки в выходной набор.
OutputTable.Set('id', id); // Установка значения заданного поля в добавленной строке.
OutputTable.Set('parent', parent);
OutputTable.Set('key', key);
OutputTable.Set('type', type);
OutputTable.Set('value', value);
}
Созданный узел парсит JSON произвольной структуры. Выходной набор в формате key-value фактически является таблицей со свернутыми столбцами. Развернуть такую таблицу в обычное представление можно при помощи компонента Кросс-таблица, предварительно выделив из нее при помощи фильтра только необходимые данные.
Пример в архиве: ParseJSONcomponent.zip