В одном из проектов возникла необходимость перевести процессы импорта данных сторонних систем на микросервисную архитектуру. В качестве инструмента выбран Apache NiFi. В качестве первого подопытного выбран импорт ЕГРЮЛ ФНС.
В предыдущей статье был описан способ преобразования XML в JSON с использованием AVRO schema.
В данной статье описан способ преобразования JSON с помощью JOLT спецификации.
Используемые процессоры и контроллеры
Деление JSON на части
FlowFile, полученный на предыдущем этапе, содержит JSON с массивом выписок ЕГРЮЛ по разным организациям. Для начала разделим его на части, чтобы каждый FlowFile содержал одну выписку.
Для этого используем процессор SplitJson. Из настроек - требуется указать выражение JsonPath для разделения json на части. В данном случае $.*

Документация по JsonPath здесь
Потренироваться можно здесь
Преобразование JSON
Полученный JSON имеет излишне сложную структуру для того, чтобы в дальнейшем хранить и обрабатывать его. Адрес и ФИО лучше объединить в одну строку, некоторые элементы перенести выше по иерархии.
JSON перед трансформацией
{
"reportDate" : "2020-05-20",
"ogrn" : "1234567890123",
"ogrnDate" : "2002-12-30",
"inn" : "1234567890",
"kpp" : "123456789",
"opfCode" : "12300",
"opfName" : "Общества с ограниченной ответственностью",
"name" : {
"fullName" : "ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ",
"shortName" : "ООО"
},
"address" : {
"addressRF" : {
"region" : {
"type" : "ОБЛАСТЬ",
"name" : "МОСКОВСКАЯ"
},
"district" : null,
"town" : {
"type" : "ГОРОД",
"name" : "ИСТРА"
},
"settlement" : null,
"street" : {
"type" : "ПЕРЕУЛОК",
"name" : "ВОЛОКОЛАМСКИЙ"
},
"index" : "143500",
"regionCode" : "50",
"kladr" : "500000570000011",
"house" : null,
"building" : null,
"apartment" : null
}
},
"termination" : null,
"capital" : null,
"manageOrg" : null,
"director" : [ {
"fl" : {
"lastName" : "ИВАНОВ",
"firstName" : "ИВАН",
"patronymic" : "ИВАНОВИЧ",
"inn" : "123456789012"
},
"position" : {
"ogrnip" : null,
"typeCode" : "02",
"typeName" : "Руководитель юридического лица",
"name" : "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР"
},
"disqualification" : null
} ],
"founders" : {
"founderULRF" : null,
"founderULForeign" : null,
"founderFL" : [ {
"fl" : {
"lastName" : "ИВАНОВ",
"firstName" : "ИВАН",
"patronymic" : "ИВАНОВИЧ",
"inn" : "123456789012"
},
"capitalPart" : {
"nominal" : 20000.0,
"size" : {
"percent" : 50.0,
"decimalPart" : null,
"simplePart" : null
}
}
}, {
"fl" : {
"lastName" : "ПЕТРОВ",
"firstName" : "ПЕТР",
"patronymic" : "ПЕТРОВИЧ",
"inn" : "123456789021"
},
"capitalPart" : {
"nominal" : 20000.0,
"size" : {
"percent" : 50.0,
"decimalPart" : null,
"simplePart" : null
}
}
} ],
"founderGov" : null,
"founderPIF" : null
},
"capitalPart" : null,
"holderReestrAO" : null,
"okved" : {
"mainOkved" : {
"code" : "47.11",
"name" : "Торговля розничная преимущественно пищевыми продуктами, включая напитки, и табачными изделиями в неспециализированных магазинах"
},
"addOkved" : null
}
}Для трансформации JSON используется процессор JoltTransformJSON.
Настройки:
Jolt Transformation DSL - тип трансформации. В данном случае Chain - цепочка из нескольких трансформаций
Jolt Specification - собственно сама спецификация. Ее разбор ниже

JOLT спецификация
Собственно, сам субъект - ссылка на исходники и документацию.
Потренироваться можно здесь.
Меня интересовали операции сдвига элементов по иерархии - операция shift и преобразование самих данных - операция modify-overwrite-beta. По последней доки как таковой и нет. Исходники операции в Modifier.java, там можно посмотреть список доступных функций. Но на jolt-demo.appspot.com внизу есть примеры для этой операции. Так что методом научного тыка есть возможность прийти к решению.
JOLT спецификация
[
{
"operation": "modify-overwrite-beta",
"spec": {
"address": {
"addressRF": {
"region": "=concat(@(type), ' ', @(name))",
"district": "=concat(@(type), ' ', @(name))",
"town": "=concat(@(type), ' ', @(name))",
"settlement": "=concat(@(type), ' ', @(name))",
"street": "=concat(@(type), ' ', @(name))"
}
},
"director": {
"*": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
},
"founders": {
"founderFL": {
"*": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
},
"founderGov": {
"*": {
"founderImplFL": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
}
}
}
}
},
{
"operation": "modify-overwrite-beta",
"spec": {
"address": {
"addressRF": {
"value": "=concat(@(1,index), ', ', @(1,region), ', ', @(1,district), ', ', @(1,town), ', ', @(1,settlement), ', ', @(1,street), ', ', @(1,house), ', ', @(1,building), ', ', @(1,apartment))",
"fias": null
}
}
}
},
{
"operation": "shift",
"spec": {
"reportDate|ogrn|ogrnDate|inn|kpp|opfCode|opfName": "&",
"name": {
"*": "&"
},
"address": {
"addressRF": {
"kladr|regionCode|value|fias": "&2.&"
}
},
"termination": {
"method": {
"*": "&2.&"
},
"*": "&1.&"
},
"capital": "&",
"manageOrg": {
"egrulData": {
"*": "&2.&"
}
},
"director": {
"*": {
"fl": {
"fio|inn": "&3[&2].&"
},
"position": {
"name": "&3[&2].&1",
"*": "&3[&2].&"
},
"disqualification": "&2[&1].&"
}
},
"founders": {
"founderULRF|founderULForeign": {
"*": {
"egrulData|foreignReg": {
"*": "&4.&3[&2].&"
},
"*": "&3.&2[&1].&"
}
},
"founderFL": {
"*": {
"fl": {
"fio|inn": "&4.&3[&2].&"
},
"*": "&3.&2[&1].&"
}
},
"founderGov": {
"*": {
"govOrg": {
"*": "&4.&3[&2].&"
},
"capitalPart": "&3.&2[&1].&",
"founderImplUL": {
"egrulData": {
"*": "&5.&4[&3].&2.&"
}
},
"founderImplFL": {
"fl": {
"fio|inn": "&5.&4[&3].&2.&"
}
}
}
},
"founderPIF": {
"*": {
"PIFName": {
"name": "&4.&3[&2].&1"
},
"manageOrg": {
"egrulData": {
"*": "&5.&4[&3].&"
}
},
"capitalPart": "&3.&2[&1].&"
}
}
},
"capitalPart": "&",
"holderReestrAO": {
"egrulData": {
"*": "&2.&"
}
},
"okved": "&"
}
}
]Операцию modify-overwrite-beta пришлось делать два раза, т.к. по другому собрать адрес в одну строку у меня не получилось.
Как видно, вся спецификация представляет собой массив из трех операций: две - modify-overwrite-beta и одна - shift. Описание каждой операции содержит ее тип - элемент operation и спецификацию - элемент spec.
Преобразование выполняется по цепочке от первого к последнему блоку таким образом, что выходные данные каждого блока служат входными данными для следующего.
Операция modify-overwrite-beta
Спецификация операции содержит левую и правую часть. В левой части требуется указать путь к элементу, который должен быть получен на выходе. В правой части указывается, каким образом должно быть получено содержимое элемента.
Преобразование адреса
Разберем преобразование адреса.
Первый этап (см. первый блок modify-overwrite-beta) - объединить type и name для region, district, town, settlement и street. Для этого прописываем путь к элементам и в правой части для каждого пишем "=concat(@(type), ' ', @(name))" .
"address": {
"addressRF": {
"region": "=concat(@(type), ' ', @(name))",
"district": "=concat(@(type), ' ', @(name))",
"town": "=concat(@(type), ' ', @(name))",
"settlement": "=concat(@(type), ' ', @(name))",
"street": "=concat(@(type), ' ', @(name))"
}
}Что это означает. Например, "region": "=concat(@(type), ' ', @(name))", означает: на выходе требуется получить элемент region, а в качестве его содержимого требуется получить конкатенацию содержимого элементов type и name. Причем искать эти элементы необходимо непосредственно внутри существующего элемента region, о чем говорит конструкция @(type).
Второй этап (см. второй блок modify-overwrite-beta) - объединить составляющие адреса в одну строку и записать в элемент value.
"address": {
"addressRF": {
"value": "=concat(@(1,index), ', ', @(1,region), ', ', @(1,district), ', ', @(1,town), ', ', @(1,settlement), ', ', @(1,street), ', ', @(1,house), ', ', @(1,building), ', ', @(1,apartment))",
"fias": null
}
}Здесь примерно то же самое, но теперь используется конструкция вида @(1,index). Она означает, что для поиска элемента index необходимо подняться на один уровень вверх от текущего и искать его там. Т.е. от уровня value необходимо перейти к уровню addressRF, и в пределах addressRF найти элемент index.
Следует обратить внимание, что не должно быть пробелов между = и concat, а также в @(1,index).
Элемент fias был добавлен в надежде в дальнейшем осуществить поиск кода ФИАС по адресу в каком-нибудь стороннем сервисе.
На этом преобразование адреса завершено. Про операцию shift будет ниже.
Объединение ФИО для физически�� лиц
Объединение ФИО для физических лиц осуществляется аналогичным образом. Здесь обращает на себя внимание только наличие селектора "*" в левой части. Он используется, т.к. содержимое элемента director представляет собой массив, а это отдельный уровень иерархии.
"director": {
"*": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
}Операция shift
В блок shift на вход поступает следующий JSON.
Промежуточный JSON
{
"reportDate" : "2020-05-20",
"ogrn" : "1234567890123",
"ogrnDate" : "2002-12-30",
"inn" : "1234567890",
"kpp" : "123456789",
"opfCode" : "12300",
"opfName" : "Общества с ограниченной ответственностью",
"name" : {
"fullName" : "ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ",
"shortName" : "ООО"
},
"address" : {
"addressRF" : {
"region" : "ОБЛАСТЬ МОСКОВСКАЯ",
"district" : " ",
"town" : "ГОРОД ИСТРА",
"settlement" : " ",
"street" : "ПЕРЕУЛОК ВОЛОКОЛАМСКИЙ",
"index" : "143500",
"regionCode" : "50",
"kladr" : "500000570000011",
"house" : null,
"building" : null,
"apartment" : null,
"value" : "143500, ОБЛАСТЬ МОСКОВСКАЯ, , ГОРОД ИСТРА, , ПЕРЕУЛОК ВОЛОКОЛАМСКИЙ, , , ",
"fias" : null
}
},
"termination" : null,
"capital" : null,
"manageOrg" : null,
"director" : [ {
"fl" : {
"lastName" : "ИВАНОВ",
"firstName" : "ИВАН",
"patronymic" : "ИВАНОВИЧ",
"inn" : "123456789012",
"fio" : "ИВАНОВ ИВАН ИВАНОВИЧ"
},
"position" : {
"ogrnip" : null,
"typeCode" : "02",
"typeName" : "Руководитель юридического лица",
"name" : "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР"
},
"disqualification" : null
} ],
"founders" : {
"founderULRF" : null,
"founderULForeign" : null,
"founderFL" : [ {
"fl" : {
"lastName" : "ИВАНОВ",
"firstName" : "ИВАН",
"patronymic" : "ИВАНОВИЧ",
"inn" : "123456789012",
"fio" : "ИВАНОВ ИВАН ИВАНОВИЧ"
},
"capitalPart" : {
"nominal" : 20000,
"size" : {
"percent" : 50,
"decimalPart" : null,
"simplePart" : null
}
}
}, {
"fl" : {
"lastName" : "ПЕТРОВ",
"firstName" : "ПЕТР",
"patronymic" : "ПЕТРОВИЧ",
"inn" : "123456789021",
"fio" : "ПЕТРОВ ПЕТР ПЕТРОВИЧ"
},
"capitalPart" : {
"nominal" : 20000,
"size" : {
"percent" : 50,
"decimalPart" : null,
"simplePart" : null
}
}
} ],
"founderGov" : null,
"founderPIF" : null
},
"capitalPart" : null,
"holderReestrAO" : null,
"okved" : {
"mainOkved" : {
"code" : "47.11",
"name" : "Торговля розничная преимущественно пищевыми продуктами, включая напитки, и табачными изделиями в неспециализированных магазинах"
},
"addOkved" : null
}
}Как видно, остались лишние элементы - например, данные адреса, фамилия, имя отчество. Стоит отметить, что если в операции modify-overwrite-beta не указано преобразование для элемента, то он переносится в неизменном виде. В отличие от этого, в операции shift - если преобразование для элемента не указано, то он будет удален.
Описание операции shift
{
"operation": "shift",
"spec": {
"reportDate|ogrn|ogrnDate|inn|kpp|opfCode|opfName": "&",
"name": {
"*": "&"
},
"address": {
"addressRF": {
"kladr|regionCode|value|fias": "&2.&"
}
},
"termination": {
"method": {
"*": "&2.&"
},
"*": "&1.&"
},
"capital": "&",
"manageOrg": {
"egrulData": {
"*": "&2.&"
}
},
"director": {
"*": {
"fl": {
"fio|inn": "&3[&2].&"
},
"position": {
"name": "&3[&2].&1",
"*": "&3[&2].&"
},
"disqualification": "&2[&1].&"
}
},
"founders": {
"founderULRF|founderULForeign": {
"*": {
"egrulData|foreignReg": {
"*": "&4.&3[&2].&"
},
"*": "&3.&2[&1].&"
}
},
"founderFL": {
"*": {
"fl": {
"fio|inn": "&4.&3[&2].&"
},
"*": "&3.&2[&1].&"
}
},
"founderGov": {
"*": {
"govOrg": {
"*": "&4.&3[&2].&"
},
"capitalPart": "&3.&2[&1].&",
"founderImplUL": {
"egrulData": {
"*": "&5.&4[&3].&2.&"
}
},
"founderImplFL": {
"fl": {
"fio|inn": "&5.&4[&3].&2.&"
}
}
}
},
"founderPIF": {
"*": {
"PIFName": {
"name": "&4.&3[&2].&1"
},
"manageOrg": {
"egrulData": {
"*": "&5.&4[&3].&"
}
},
"capitalPart": "&3.&2[&1].&"
}
}
},
"capitalPart": "&",
"holderReestrAO": {
"egrulData": {
"*": "&2.&"
}
},
"okved": "&"
}
}В операции shift присутствуют левая и правая часть инструкции. Левая часть указывает, где брать данные, а правая указывает путь, куда их разместить. Путь представляет собой цепочку наименований элементов, разделенных точкой. С помощью знака & осуществляется подстановка наименований существующих элементов. Исчисление начинается с того элемента, который указан в левой части, ему соответствует &0. Ноль при этом можно опустить. Выше него по иерархии будет &1, и т.д. К знакам & можно добавлять префиксы и суффиксы - например, pre-&-post. Т.е. если & соответствует элементу name, то на выходе получим pre-name-post. Результирующая цепочка элементов размещается в корне иерархии. Рассмотрим на примерах.
Самое простое - "reportDate|ogrn|ogrnDate|inn|kpp|opfCode|opfName": "&". Будет взят каждый из перечисленных элементов, и они будут размещены в корне. Перечисление осуществляется с помощью |.
Далее переносим fullName и shortName на один уровень вверх с помощью инструкции "name": { "*": "&" }."*" означает, что требуется выбрать содержимое всех элементов, вложенных в name."&" означает, что их требуется разместить в корне иерархии.
Следующее - перенос данных адреса.
"address": {
"addressRF": {
"kladr|regionCode|value|fias": "&2.&"
}
}Здесь мы указываем нужные элементы. Ненужные не указываем. Инструкция для размещения - "&2.&". Она означает, что требуется составить цепочки из нулевого и второго уровня, минуя первый. &2 соответствует элементу address, а & - элементам из перечисления. &1 соответствует элементу addressRF, он будет удален из иерархии. Т.обр. будут составлены четыре цепочки: address.kladr, address.regionCode, address.value и address.fias. И все они буду размещены в корне результирующего JSON.
Массивы разберем на примере данных о директоре
"director" : [ {
"fl" : {
"lastName" : "ИВАНОВ",
"firstName" : "ИВАН",
"patronymic" : "ИВАНОВИЧ",
"inn" : "123456789012",
"fio" : "ИВАНОВ ИВАН ИВАНОВИЧ"
},
"position" : {
"ogrnip" : null,
"typeCode" : "02",
"typeName" : "Руководитель юридического лица",
"name" : "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР"
},
"disqualification" : null
} ]Нужно убрать lastName, firstName и patronymic.
inn и fio перенести на один уровень выше.
ogrnip, typeCode и typeName также перенести на один уровень выше.
Значение name установить в качестве значения position.
disqualification оставить без изменений.
В общем-то алгоритм действий тот же самый, но следуют помнить, что массив - это отдельный уровень иерархии. Когда работаем с массивом, то в цепочке иерархии соответствующий ему & должен быть помещен в квадратные скобки - [&].
"director": {
"*": {
"fl": {
"fio|inn": "&3[&2].&"
},
"position": {
"name": "&3[&2].&1",
"*": "&3[&2].&"
},
"disqualification": "&2[&1].&"
}
}Например, fio и inn. Для них цепочка &3[&2].&. Точку перед открывающей квадратной скобкой можно опустить. Получаем: &3 - соответствует элементу director, [&2] - соответствует уровню элементов массива, & - сами fio и inn.
Элемент name в position. &3 - соответствует элементу director, [&2] - соответствует уровню элементов массива, &1 - соответствует элементу position. &, соответствующий самому элементу name отсутствует, значит его содержимое будет перенесено в position.
Остальные элементы в position просто переносятся на один уровень вверх. disqualification остается без изменений.
Далее используются аналогичные конструкции.
Пример
Ну и напоследок продублирую исходный JSON, JOLT спецификацию и результирующий JSON
Исходный JSON
{
"reportDate": "2020-05-20",
"ogrn": "1234567890123",
"ogrnDate": "2002-12-30",
"inn": "1234567890",
"kpp": "123456789",
"opfCode": "12300",
"opfName": "Общества с ограниченной ответственностью",
"name": {
"fullName": "ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ",
"shortName": "ООО"
},
"address": {
"addressRF": {
"region": {
"type": "ОБЛАСТЬ",
"name": "МОСКОВСКАЯ"
},
"district": null,
"town": {
"type": "ГОРОД",
"name": "ИСТРА"
},
"settlement": null,
"street": {
"type": "ПЕРЕУЛОК",
"name": "ВОЛОКОЛАМСКИЙ"
},
"index": "143500",
"regionCode": "50",
"kladr": "500000570000011",
"house": null,
"building": null,
"apartment": null
}
},
"termination": null,
"capital": null,
"manageOrg": null,
"director": [
{
"fl": {
"lastName": "ИВАНОВ",
"firstName": "ИВАН",
"patronymic": "ИВАНОВИЧ",
"inn": "123456789012"
},
"position": {
"ogrnip": null,
"typeCode": "02",
"typeName": "Руководитель юридического лица",
"name": "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР"
},
"disqualification": null
}
],
"founders": {
"founderULRF": null,
"founderULForeign": null,
"founderFL": [
{
"fl": {
"lastName": "ИВАНОВ",
"firstName": "ИВАН",
"patronymic": "ИВАНОВИЧ",
"inn": "123456789012"
},
"capitalPart": {
"nominal": 20000,
"size": {
"percent": 50,
"decimalPart": null,
"simplePart": null
}
}
},
{
"fl": {
"lastName": "ПЕТРОВ",
"firstName": "ПЕТР",
"patronymic": "ПЕТРОВИЧ",
"inn": "123456789021"
},
"capitalPart": {
"nominal": 20000,
"size": {
"percent": 50,
"decimalPart": null,
"simplePart": null
}
}
}
],
"founderGov": null,
"founderPIF": null
},
"capitalPart": null,
"holderReestrAO": null,
"okved": {
"mainOkved": {
"code": "47.11",
"name": "Торговля розничная преимущественно пищевыми продуктами, включая напитки, и табачными изделиями в неспециализированных магазинах"
},
"addOkved": null
}
}JOLT спецификация
[
{
"operation": "modify-overwrite-beta",
"spec": {
"address": {
"addressRF": {
"region": "=concat(@(type), ' ', @(name))",
"district": "=concat(@(type), ' ', @(name))",
"town": "=concat(@(type), ' ', @(name))",
"settlement": "=concat(@(type), ' ', @(name))",
"street": "=concat(@(type), ' ', @(name))"
}
},
"director": {
"*": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
},
"founders": {
"founderFL": {
"*": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
},
"founderGov": {
"*": {
"founderImplFL": {
"fl": {
"fio": "=concat(@(1,lastName), ' ', @(1,firstName), ' ', @(1,patronymic))"
}
}
}
}
}
}
},
{
"operation": "modify-overwrite-beta",
"spec": {
"address": {
"addressRF": {
"value": "=concat(@(1,index), ', ', @(1,region), ', ', @(1,district), ', ', @(1,town), ', ', @(1,settlement), ', ', @(1,street), ', ', @(1,house), ', ', @(1,building), ', ', @(1,apartment))",
"fias": null
}
}
}
},
{
"operation": "shift",
"spec": {
"reportDate|ogrn|ogrnDate|inn|kpp|opfCode|opfName": "&",
"name": {
"*": "&"
},
"address": {
"addressRF": {
"kladr|regionCode|value|fias": "&2.&"
}
},
"termination": {
"method": {
"*": "&2.&"
},
"*": "&1.&"
},
"capital": "&",
"manageOrg": {
"egrulData": {
"*": "&2.&"
}
},
"director": {
"*": {
"fl": {
"fio|inn": "&3[&2].&"
},
"position": {
"name": "&3[&2].&1",
"*": "&3[&2].&"
},
"disqualification": "&2[&1].&"
}
},
"founders": {
"founderULRF|founderULForeign": {
"*": {
"egrulData|foreignReg": {
"*": "&4.&3[&2].&"
},
"*": "&3.&2[&1].&"
}
},
"founderFL": {
"*": {
"fl": {
"fio|inn": "&4.&3[&2].&"
},
"*": "&3.&2[&1].&"
}
},
"founderGov": {
"*": {
"govOrg": {
"*": "&4.&3[&2].&"
},
"capitalPart": "&3.&2[&1].&",
"founderImplUL": {
"egrulData": {
"*": "&5.&4[&3].&2.&"
}
},
"founderImplFL": {
"fl": {
"fio|inn": "&5.&4[&3].&2.&"
}
}
}
},
"founderPIF": {
"*": {
"PIFName": {
"name": "&4.&3[&2].&1"
},
"manageOrg": {
"egrulData": {
"*": "&5.&4[&3].&"
}
},
"capitalPart": "&3.&2[&1].&"
}
}
},
"capitalPart": "&",
"holderReestrAO": {
"egrulData": {
"*": "&2.&"
}
},
"okved": "&"
}
}
]
Результирующий JSON
{
"reportDate" : "2020-05-20",
"ogrn" : "1234567890123",
"ogrnDate" : "2002-12-30",
"inn" : "1234567890",
"kpp" : "123456789",
"opfCode" : "12300",
"opfName" : "Общества с ограниченной ответственностью",
"fullName" : "ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ",
"shortName" : "ООО",
"address" : {
"kladr" : "500000570000011",
"regionCode" : "50",
"value" : "143500, ОБЛАСТЬ МОСКОВСКАЯ, , ГОРОД ИСТРА, , ПЕРЕУЛОК ВОЛОКОЛАМСКИЙ, , , ",
"fias" : null
},
"capital" : null,
"director" : [ {
"fio" : "ИВАНОВ ИВАН ИВАНОВИЧ",
"inn" : "123456789012",
"ogrnip" : null,
"typeCode" : "02",
"typeName" : "Руководитель юридического лица",
"position" : "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР",
"disqualification" : null
} ],
"founders" : {
"founderFL" : [ {
"fio" : "ИВАНОВ ИВАН ИВАНОВИЧ",
"inn" : "123456789012",
"capitalPart" : {
"nominal" : 20000,
"size" : {
"percent" : 50,
"decimalPart" : null,
"simplePart" : null
}
}
}, {
"fio" : "ПЕТРОВ ПЕТР ПЕТРОВИЧ",
"inn" : "123456789021",
"capitalPart" : {
"nominal" : 20000,
"size" : {
"percent" : 50,
"decimalPart" : null,
"simplePart" : null
}
}
} ]
},
"capitalPart" : null,
"okved" : {
"mainOkved" : {
"code" : "47.11",
"name" : "Торговля розничная преимущественно пищевыми продуктами, включая напитки, и табачными изделиями в неспециализированных магазинах"
},
"addOkved" : null
}
}Далее
Далее получившийся JSON следует куда-то разместить для хранения и дальнейшего использования. Но это выходит за рамки повествования. Тут уж кому что удобно.
