Talend:将JSON行转换为列,从JSON中提取列名
我有一个json rest响应,其结构类似于:Talend:将JSON行转换为列,从JSON中提取列名,talend,Talend,我有一个json rest响应,其结构类似于: { "data" : [ { "fields" : [ { "label" : "John", "value" : "John" }, { "label" : "Smith", "value" : "/person/4315" }, { "label" : "43", "value" : "43" },
{
"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来处理这个问题,但我想知道是否有更标准的方法
我是塔伦德的新手,所以我花了几个小时来尝试,但由于我的尝试可能完全错误,所以我不会在这里描述
谢谢你的帮助。这里有一个完全动态的解决方案 首先,您需要读取json以获取列列表。以下是tExtractJSONFields_2的外观: 然后将列及其位置存储在tHashOutput中(需要在文件>项目属性>设计器>调色板设置中取消隐藏)。在tMap_2中,使用序列获取列的位置:
Numeric.sequence("s", 1, 1)
(Numeric.sequence("s1", 0, 1) % ((Integer)globalMap.get("tHashOutput_1_NB_LINE"))) + 1
本主题的输出为:
|=-------+--------=|
|position|column |
|=-------+--------=|
|1 |firstname|
|2 |lastname |
|3 |age |
|4 |city |
'--------+---------'
第二步是再次读取json,以便解析fields属性。
与步骤1一样,您需要向每个字段添加相对于列的位置。下面是我用来获取序列的表达式:
Numeric.sequence("s", 1, 1)
(Numeric.sequence("s1", 0, 1) % ((Integer)globalMap.get("tHashOutput_1_NB_LINE"))) + 1
请注意,我使用的是不同的序列名称,因为序列在整个作业中保持其值。我使用tHashOutput_1中的列数来保持动态。以下是此子对象的输出:
|=-------+---------+---------------=|
|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 |
'--------+---------+----------------'
在最后一个子主题中,您需要使用存储的列位置将字段数据与列连接起来。
在tSplitRow_1中,我为每个传入行生成2行。每行是一个键值对。第一行是\u label
(与firstname\u label、lastname\u label类似),其值是字段中的标签。第二行的键是\u value
,其值是字段中的值
再一次,我们需要在tMap_4中的数据中添加一个位置,使用以下表达式:
(Numeric.sequence("s2", 0, 1) / ((Integer)globalMap.get("tHashOutput_1_NB_LINE") * 2)) + 1
请注意,由于tSplitRow的行数是tSplitRow的两倍,因此我将列数乘以2。这将为需要在输出文件的同一行上的数据赋予相同的ID。 此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,它将使用唯一ID将我们的行转换为列
最终结果是一个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
请注意,在开头有一个无关的列,它是行id,通过读取文件并将其删除,可以轻松删除该行id。我尝试在输入json中添加一个新列以及相应的字段,效果如预期。非常感谢易卜拉欣的努力。你的回答很清楚。我会尽快测试它,并在成功完成后验证您的答案。很高兴让我知道;)这里有一个关于如何删除额外id列的解决方案,我必须对其进行调整,因为我的示例只是一个示例,我的json有点复杂,但它工作得很好。干得好!再次谢谢。很高兴听到这个消息!