Talend: преобразование JSON строк в столбцы, извлечение имен столбцов из JSON - PullRequest
1 голос
/ 08 апреля 2020

У меня есть json ответ покоя со структурой, похожей на эту:

{
    "data" : [
        {
            "fields" : [
                { "label" : "John", "value" : "John" },
                { "label" : "Smith", "value" : "/person/4315" },
                { "label" : "43", "value" : "43" },
                { "label" : "London", "value" : "/city/54" }
            ]
        },
        {
            "fields" : [
                { "label" : "Albert", "value" : "Albert" },
                { "label" : "Einstein", "value" : "/person/154" },
                { "label" : "141", "value" : "141" },
                { "label" : "Princeton", "value" : "/city/9541" }
            ]
        }
    ],
    "columns" : ["firstname", "lastname", "age", "city"]
}

Я ищу способ преобразовать эти данные в строки типа

| first_name_label  | firstname_value | lastname_label | lastname_value | age_label | age_value | city_label | city_value |
---------------------------------------------------------------------------------------------------------------------------
|      John         |   John          | Smith          |  /person/4315  |  43       |    43     |    London  |  /city/54  |
|      Albert       |   Albert        | Einstein       |  /person/154   |  141      |    141    |  Princeton | /city/9541 |

Конечно, количество столбцов и их имена могут измениться, поэтому я не знаю схему до времени выполнения. Я, вероятно, могу написать java, чтобы справиться с этим, но я хотел бы знать, есть ли более стандартный способ.

Я новичок в Talend, поэтому я потратил часы, пытаясь, но так как мои попытки, вероятно, были полностью неправильными Я не буду описывать это здесь.

Спасибо за вашу помощь.

1 Ответ

1 голос
/ 08 апреля 2020

Вот полностью динамическое c решение, которое я собрал.

enter image description here

Сначала вам нужно прочитать json, чтобы получить список столбцов. Вот как выглядит tExtractJSONFields_2:

enter image description here

Затем вы сохраняете столбцы и их позиции в tHashOutput (его необходимо отобразить в File> Project properties> Дизайнер> Настройки палитры). В tMap_2 вы получаете положение столбца, используя последовательность:

Numeric.sequence("s", 1, 1) 

Выход этого подзадачи:

|=-------+--------=|
|position|column   |
|=-------+--------=|
|1       |firstname|
|2       |lastname |
|3       |age      |
|4       |city     |
'--------+---------'

2-й шаг - снова прочитать json , чтобы разобрать свойства полей. enter image description here Как и в шаге 1, вам необходимо добавить позицию к каждому полю относительно столбцов. Вот выражение, которое я использовал для получения последовательности:

(Numeric.sequence("s1", 0, 1) % ((Integer)globalMap.get("tHashOutput_1_NB_LINE"))) + 1 

Обратите внимание, что я использую другое имя последовательности, потому что последовательности сохраняют свое значение на протяжении всей работы. Я использую количество столбцов из tHashOutput_1 для того, чтобы все было динамично c.
Вот вывод этой подзадачи:

|=-------+---------+---------------=|
|position|label    |value           |
|=-------+---------+---------------=|
|1       |John     |John            |
|2       |Smith    |/person/4315    |
|3       |43       |43              |
|4       |London   |/city/54        |
|1       |Albert   |Albert          |
|2       |Einstein |/person/154     |
|3       |141      |141             |
|4       |Princeton|/city/9541      |
'--------+---------+----------------'

В последнем подзадаче вам нужно объединить поля данные со столбцами, используя положение столбца мы сохранили с любым enter image description here

В tSplitRow_1 я генерирую 2 строки для каждой входящей строки. Каждая строка является парой ключ-значение. Первая строка - <columnName>_label (как firstname_label, lastname_label), ее значение является меткой из полей. Ключ 2-й строки - <columnName>_value, а его значением является значение из полей.

enter image description here

Еще раз нам нужно добавить позицию в наши данные в tMap_4, используя это выражение:

(Numeric.sequence("s2", 0, 1) / ((Integer)globalMap.get("tHashOutput_1_NB_LINE") * 2)) + 1

Обратите внимание, что, поскольку у нас есть в два раза больше строк, выходящих из tSplitRow, я умножу количество столбцов на 2.
Это будет приписывать тот же идентификатор для данных, которые должны быть в той же строке в выходном файле. Вывод этого tMap будет выглядеть следующим образом:

|=-+---------------+-----------=|
|id|col_label      |col_value   |
|=-+---------------+-----------=|
|1 |firstname_label|John        |
|1 |firstname_value|John        |
|1 |lastname_label |Smith       |
|1 |lastname_value |/person/4315|
|1 |age_label      |43          |
|1 |age_value      |43          |
|1 |city_label     |London      |
|1 |city_value     |/city/54    |
|2 |firstname_label|Albert      |
|2 |firstname_value|Albert      |
|2 |lastname_label |Einstein    |
|2 |lastname_value |/person/154 |
|2 |age_label      |141         |
|2 |age_value      |141         |
|2 |city_label     |Princeton   |
|2 |city_value     |/city/9541  |
'--+---------------+------------'

Это приведет нас к последнему компоненту tPivotToColumnsDelimited, который будет поворачивать наши строки в столбцы, используя уникальный идентификатор.

enter image description here

И окончательный результат - файл CSV, такой как:

id;firstname_label;firstname_value;lastname_label;lastname_value;age_label;age_value;city_label;city_value
1;John;John;Smith;/person/4315;43;43;London;/city/54
2;Albert;Albert;Einstein;/person/154;141;141;Princeton;/city/9541

Обратите внимание, что в начале вы получите посторонний столбец, который является идентификатором строки, который можно легко удалить прочитав файл и удалив его.
Я попытался добавить новый столбец вместе с соответствующими полями во входных данных json, и он работает, как и ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...