Dataweave 将 xml 的重复元素合并到以节点路径为键的对象中
Dataweave combine repeated element of xml into object with path to node as keys
我在 dw playground 中有以下 XML 及其 json 对应部分:
%dw 2.0
output application/json
---
payload
<insurance>
<info>
<pid>101</pid>
<pid>102</pid>
<pid>103</pid>
<pid>104</pid>
</info>
<details>
<rid>21</rid>
<rid>22</rid>
<rid>23</rid>
</details>
</insurance>
{
"insurance": {
"info": {
"pid": "101",
"pid": "102",
"pid": "103",
"pid": "104"
},
"details": {
"rid": "21",
"rid": "22",
"rid": "23"
}
}
}
我的要求是将其转换为 {"root to node path": "array of values"} 。下面给出的是我的尝试,但没有成功,因为 DW 将重复的字段转换为单独的键而不是数组。
**EXPECTED:**
{
"root-insurance-info-pid": [101, 102, 103, 104],
"root-insurace-details-rid": [21, 22, 23]
}
**ACTUAL:**
{
"root-insurance-info-pid": 101,
"root-insurance-info-pid": 102,
...
"root-insurace-details-rid": 23
}
fun generate(obj ,parentKey) =
obj match {
case is Object -> obj mapObject ((value, key, index) ->
generate(value, parentKey ++ "-" ++ (key as String))
)
case is Array -> {(parentKey): obj}
else -> {(parentKey): obj}
}
---
generate(payload, "root")
- 有没有办法做到这一点,确保一切都保持动态。由于嵌套级别可能会有所不同。
- 输入XML可以进行哪些修改?
问题是XML里面没有数组的概念。这些只是在同一父级下具有相同键的元素列表。如果您可以向 XML 输入添加一个属性以指示脚本要考虑哪些元素 'arrays',那么处理它们会更容易。假设那些 'arrays' 都共享相同的密钥:
%dw 2.0
output application/json
fun getFirstKey(o)=keysOf(o)[0] // assumes in an array element all subkeys are the same
fun generate(obj ,parentKey) =
obj match {
case is Object ->
if (obj.@array == "true")
{(parentKey ++ "-" ++ getFirstKey(obj) as String): valuesOf(obj)}
else obj mapObject ((value, key, index) -> generate(value, parentKey ++ "-" ++ (key as String)))
case a is Array -> {(parentKey): a}
else -> {(parentKey): obj}
}
---
generate(payload, "root")
输出:
{
"root-insurance-info-pid": [
"101",
"102",
"103",
"104"
],
"root-insurance-details-rid": [
"21",
"22",
"23"
]
}
在不更改 XML 的情况下,您可以通过添加检查来获得相同的结果,检查对象何时具有其所有键都具有相同的名称并且每个值都是基本类型而不是更多对象。
我在 dw playground 中有以下 XML 及其 json 对应部分:
%dw 2.0
output application/json
---
payload
<insurance>
<info>
<pid>101</pid>
<pid>102</pid>
<pid>103</pid>
<pid>104</pid>
</info>
<details>
<rid>21</rid>
<rid>22</rid>
<rid>23</rid>
</details>
</insurance>
{
"insurance": {
"info": {
"pid": "101",
"pid": "102",
"pid": "103",
"pid": "104"
},
"details": {
"rid": "21",
"rid": "22",
"rid": "23"
}
}
}
我的要求是将其转换为 {"root to node path": "array of values"} 。下面给出的是我的尝试,但没有成功,因为 DW 将重复的字段转换为单独的键而不是数组。
**EXPECTED:**
{
"root-insurance-info-pid": [101, 102, 103, 104],
"root-insurace-details-rid": [21, 22, 23]
}
**ACTUAL:**
{
"root-insurance-info-pid": 101,
"root-insurance-info-pid": 102,
...
"root-insurace-details-rid": 23
}
fun generate(obj ,parentKey) =
obj match {
case is Object -> obj mapObject ((value, key, index) ->
generate(value, parentKey ++ "-" ++ (key as String))
)
case is Array -> {(parentKey): obj}
else -> {(parentKey): obj}
}
---
generate(payload, "root")
- 有没有办法做到这一点,确保一切都保持动态。由于嵌套级别可能会有所不同。
- 输入XML可以进行哪些修改?
问题是XML里面没有数组的概念。这些只是在同一父级下具有相同键的元素列表。如果您可以向 XML 输入添加一个属性以指示脚本要考虑哪些元素 'arrays',那么处理它们会更容易。假设那些 'arrays' 都共享相同的密钥:
%dw 2.0
output application/json
fun getFirstKey(o)=keysOf(o)[0] // assumes in an array element all subkeys are the same
fun generate(obj ,parentKey) =
obj match {
case is Object ->
if (obj.@array == "true")
{(parentKey ++ "-" ++ getFirstKey(obj) as String): valuesOf(obj)}
else obj mapObject ((value, key, index) -> generate(value, parentKey ++ "-" ++ (key as String)))
case a is Array -> {(parentKey): a}
else -> {(parentKey): obj}
}
---
generate(payload, "root")
输出:
{
"root-insurance-info-pid": [
"101",
"102",
"103",
"104"
],
"root-insurance-details-rid": [
"21",
"22",
"23"
]
}
在不更改 XML 的情况下,您可以通过添加检查来获得相同的结果,检查对象何时具有其所有键都具有相同的名称并且每个值都是基本类型而不是更多对象。