JSON 数组迭代 - Mulesoft 中的树遍历
JSON Array Iteration - Tree Traversing in Mulesoft
输入JSON:
{
"id": "/",
"code": "/",
"typeCode": "CPC",
"timeStamp": "2021-11-16T17:00:00-06:00",
"childList": [
{
"id": "577-1-1",
"code": "1111",
"name": "Electronics-1-1",
"displayName": "Electronics-1-1",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": [
{
"id": "579-2-1",
"code": "2222",
"name": "Calculators-2-1",
"displayName": "Calculators-2-1",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": []
},
{
"id": "509-2-2",
"code": "3333",
"name": "Oven-2-2",
"displayName": "Oven-2-2",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": [
{
"id": "749-3-1",
"code": "4444",
"name": "MicroOven-3-1",
"displayName": "MicroOven-3-1",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": []
}
]
}
]
},
{
"id": "549-1-2",
"code": "5555",
"name": "Refrigerator-1-2",
"displayName": "Refrigerator-1-2",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": []
}
]
}
- 而预期的 XML 如下 - 这里必须注意 categoryPath 以获取 childElement 的完整地址,并且必须分组在第一个父 childList
下
- 我们不知道任何数组的确切子元素,即 childList 中可以有“n”个 childList
- 如果 childList 元素是空数组 - 我们需要映射到 xml 并停止。否则在该数组内继续并为那些子元素做映射
XML 转换:
<Category CategoryId="${childList.id}" CategoryPath="${childList.code}/${childList.childList.code}" Description="${childList.name}" ShortDescription="${childList.displayName}">
<Extn ExtnSyncTS="${headers.timeStamp}"/>
</Category>
预期 XML:
<CategoryListArray>
<CategoryList>
<Category CategoryId="577-1-1" CategoryPath="1111" Description="Electronics-1-1" ShortDescription="Electronics-1-1">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
<Category CategoryId="579-2-1" CategoryPath="1111/2222" Description="Calculators-2-1" ShortDescription="Calculators-2-1">
<Extn ExtnSyncTS=" "/>
</Category>
<Category CategoryId="509-2-2" CategoryPath="1111/3333" Description="Oven-2-2" ShortDescription="Oven-2-2">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
<Category CategoryId="749-3-1" CategoryPath="1111/3333/4444" Description="MicroOven-3-1" ShortDescription="MicroOven-3-1">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
</CategoryList>
<CategoryList>
<Category CategoryId="549-1-2" CategoryPath="5555" Description="Refrigerator-3-1" ShortDescription="Refrigerator-3-1">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
</CategoryList>
</CategoryListArray>
您可以使用按类型匹配的递归函数来横切子树,因此它知道如何横切。然后您需要将当前节点连接到它的子节点,以便它们在输出中处于同一级别。对于数组,您应该使用 flatMap() 来避免嵌套数组。最后,XML 输出不支持数组,因此您需要将数组转换为对象。为此我使用了 reduce()。
%dw 2.0
output application/xml
fun mapChildren(x, timestamp, path)=
x match {
case o is Object ->
([{
Category @(CategoryId: o.id, CategoryPath: (if (isEmpty(path)) "" else path ++ "/") ++ o.code, Description: o.name, ShortDescription: o.displayName ): {Extn: timestamp}
}]
++ mapChildren(o.childList, timestamp, (if (isEmpty(path)) "" else path ++ "/") ++ o.code))
case a is Array ->
(a flatMap mapChildren($, timestamp, path) )
else -> $
}
---
{
CategoryList:
mapChildren(payload.childList, payload.timeStamp, "")
reduce ((item, accumulator={}) -> accumulator ++ item )
}
你可以把它封装成一个函数。
输入JSON:
{
"id": "/",
"code": "/",
"typeCode": "CPC",
"timeStamp": "2021-11-16T17:00:00-06:00",
"childList": [
{
"id": "577-1-1",
"code": "1111",
"name": "Electronics-1-1",
"displayName": "Electronics-1-1",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": [
{
"id": "579-2-1",
"code": "2222",
"name": "Calculators-2-1",
"displayName": "Calculators-2-1",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": []
},
{
"id": "509-2-2",
"code": "3333",
"name": "Oven-2-2",
"displayName": "Oven-2-2",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": [
{
"id": "749-3-1",
"code": "4444",
"name": "MicroOven-3-1",
"displayName": "MicroOven-3-1",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": []
}
]
}
]
},
{
"id": "549-1-2",
"code": "5555",
"name": "Refrigerator-1-2",
"displayName": "Refrigerator-1-2",
"active": true,
"languageCode": "en",
"typeCode": "CPC",
"childList": []
}
]
}
- 而预期的 XML 如下 - 这里必须注意 categoryPath 以获取 childElement 的完整地址,并且必须分组在第一个父 childList 下
- 我们不知道任何数组的确切子元素,即 childList 中可以有“n”个 childList
- 如果 childList 元素是空数组 - 我们需要映射到 xml 并停止。否则在该数组内继续并为那些子元素做映射
XML 转换:
<Category CategoryId="${childList.id}" CategoryPath="${childList.code}/${childList.childList.code}" Description="${childList.name}" ShortDescription="${childList.displayName}">
<Extn ExtnSyncTS="${headers.timeStamp}"/>
</Category>
预期 XML:
<CategoryListArray>
<CategoryList>
<Category CategoryId="577-1-1" CategoryPath="1111" Description="Electronics-1-1" ShortDescription="Electronics-1-1">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
<Category CategoryId="579-2-1" CategoryPath="1111/2222" Description="Calculators-2-1" ShortDescription="Calculators-2-1">
<Extn ExtnSyncTS=" "/>
</Category>
<Category CategoryId="509-2-2" CategoryPath="1111/3333" Description="Oven-2-2" ShortDescription="Oven-2-2">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
<Category CategoryId="749-3-1" CategoryPath="1111/3333/4444" Description="MicroOven-3-1" ShortDescription="MicroOven-3-1">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
</CategoryList>
<CategoryList>
<Category CategoryId="549-1-2" CategoryPath="5555" Description="Refrigerator-3-1" ShortDescription="Refrigerator-3-1">
<Extn ExtnSyncTS="2021-11-16T17:00:00-06:00"/>
</Category>
</CategoryList>
</CategoryListArray>
您可以使用按类型匹配的递归函数来横切子树,因此它知道如何横切。然后您需要将当前节点连接到它的子节点,以便它们在输出中处于同一级别。对于数组,您应该使用 flatMap() 来避免嵌套数组。最后,XML 输出不支持数组,因此您需要将数组转换为对象。为此我使用了 reduce()。
%dw 2.0
output application/xml
fun mapChildren(x, timestamp, path)=
x match {
case o is Object ->
([{
Category @(CategoryId: o.id, CategoryPath: (if (isEmpty(path)) "" else path ++ "/") ++ o.code, Description: o.name, ShortDescription: o.displayName ): {Extn: timestamp}
}]
++ mapChildren(o.childList, timestamp, (if (isEmpty(path)) "" else path ++ "/") ++ o.code))
case a is Array ->
(a flatMap mapChildren($, timestamp, path) )
else -> $
}
---
{
CategoryList:
mapChildren(payload.childList, payload.timeStamp, "")
reduce ((item, accumulator={}) -> accumulator ++ item )
}
你可以把它封装成一个函数。