
本教程详细阐述了如何在使用 jolt 进行 json 转换时,解决将多个独立对象合并为一个数组内单一对象的常见问题。通过调整 jolt shift 操作中的数组索引策略,即从动态索引 [] 改为固定索引 [0],可以有效消除冗余的 {} 结构。文章还提供了优化 jolt 规范的技巧,包括将 default 操作整合到 shift 阶段,以构建更高效、更符合预期的 json 输出。
JOLT 数组对象合并与结构优化
在使用 JOLT 进行 JSON 数据转换时,经常会遇到需要将源数据中的多个字段映射到目标 JSON 结构中一个数组内的单一对象。然而,如果处理不当,JOLT 可能会为数组中的每个字段创建独立的子对象,导致输出结构与预期不符。本文将详细介绍如何通过精确控制 JOLT shift 操作中的数组索引来解决这一问题,并提供优化 JOLT 规范的实践建议。
问题场景与输入/输出示例
假设我们有一个扁平的输入 JSON 对象,需要将其中的一部分字段转换为目标 JSON 结构中 data 数组内的一个单一对象,每个字段对应一个带 value 键的嵌套结构。
输入 JSON 示例:
{
"AssetID": "1",
"AssetNumber": "2",
"AssetMaterial": "Cisco MDS 9706",
"RackUnits": "9.0",
"MaterialType": "Chassis",
"AssetName": "Cisco-MDS-9706_1",
"CustRID": "A001",
"SerialNumber": "OU812",
"Room": "ROOM5",
"Datacenter": "DC69",
"UMountingID": "86",
"CabinetAssetID": "181",
"CabinetName": "CAB666"
}期望输出 JSON 示例:
{
"data" : [
{
"6" : {
"value" : "1"
},
"7" : {
"value" : "2"
},
"8" : {
"value" : "Cisco MDS 9706"
},
"9" : {
"value" : "Cisco-MDS-9706_1"
},
"10" : {
"value" : "A001"
},
"11" : {
"value" : "OU812"
},
"12" : {
"value" : "ROOM5"
},
"13" : {
"value" : "DC69"
},
"14" : {
"value" : "86"
},
"15" : {
"value" : "181"
},
"16" : {
"value" : "CAB666"
}
}
],
"to" : "table1",
"fieldsToReturn" : [ 6, 7, 8, 9, 10, 11, 12 ]
}常见问题:冗余的数组对象
初学者在尝试将多个字段映射到数组内时,往往会使用 data[].
导致问题的 JOLT Spec 示例:
[
{
"operation": "shift",
"spec": {
"AssetID": "data[].6.value",
"AssetNumber": "data[].7.value",
"AssetMaterial": "data[].8.value",
"AssetName": "data[].9.value",
"CustRID": "data[].10.value",
"SerialNumber": "data[].11.value",
"Room": "data[].12.value",
"Datacenter": "data[].13.value",
"UMountingID": "data[].14.value",
"CabinetAssetID": "data[].15.value",
"CabinetName": "data[].16.value"
}
},
{
"operation": "default",
"spec": {
"to": "table1"
}
},
{
"operation": "default",
"spec": {
"fieldsToReturn": [6, 7, 8, 9, 10, 11, 12]
}
}
]上述 Spec 产生的输出 JSON (带有冗余 {}):
{
"data": [
{
"6": {
"value": "1"
}
},
{
"7": {
"value": "2"
}
},
{
"8": {
"value": "Cisco MDS 9706"
}
},
// ... 更多独立的子对象 ...
{
"16": {
"value": "CAB666"
}
}
],
"to": "table1",
"fieldsToReturn": [ 6, 7, 8, 9, 10, 11, 12 ]
}可以看到,data 数组中包含了多个独立的 {} 对象,每个对象只包含一个键值对,这与我们的期望不符。
解决方案:使用固定数组索引
解决此问题的关键在于,在 shift 操作中,为所有需要合并到同一数组元素的字段指定一个固定的数组索引,而不是使用 [] 动态生成新索引。例如,使用 data[0] 将所有字段都映射到 data 数组的第一个元素中。
优化后的 JOLT Spec:
[
{
"operation": "shift",
"spec": {
"AssetID": "data[0].6.value",
"AssetNumber": "data[0].7.value",
"AssetMaterial": "data[0].8.value",
"AssetName": "data[0].9.value",
"CustRID": "data[0].10.value",
"SerialNumber": "data[0].11.value",
"Room": "data[0].12.value",
"Datacenter": "data[0].13.value",
"UMountingID": "data[0].14.value",
"CabinetAssetID": "data[0].15.value",
"CabinetName": "data[0].16.value",
// 将 "to" 字段直接整合到 shift 阶段
"#table1": "to"
}
},
{
"operation": "default",
"spec": {
"fieldsToReturn": [6, 7, 8, 9, 10, 11, 12]
}
},
{
"operation": "sort"
}
]解释:
- 通过将所有目标路径中的 data[] 替换为 data[0],JOLT 会将所有匹配的输入字段值都写入 data 数组的第一个元素中。由于它们都指向同一个目标对象,因此会自然地合并为一个对象。
- "#table1": "to" 是一种 JOLT 的语法糖,它表示将字符串字面量 "table1" 作为值,映射到目标路径 to。这种方式比单独使用一个 default 操作来添加静态值更为简洁和高效。
进一步优化与注意事项
-
整合 default 操作: 原始的 default 操作用于添加 "to": "table1" 可以直接整合到 shift 阶段,如上述优化后的 Spec 所示,使用 "#
": " " 语法。 - sort 操作: sort 操作可以确保输出 JSON 对象的键值对按照字母顺序排列,这在某些场景下有助于保持输出的一致性,但并非强制要求。
- fieldsToReturn 的处理: fieldsToReturn 数组的添加仍然需要一个 default 操作,因为它是一个静态数组,不依赖于输入字段的转换。将其放在 shift 之后是合理的。
最终的 JOLT Spec 和输出
结合上述优化,最终推荐的 JOLT Spec 如下:
[
{
"operation": "shift",
"spec": {
"AssetID": "data[0].6.value",
"AssetNumber": "data[0].7.value",
"AssetMaterial": "data[0].8.value",
"AssetName": "data[0].9.value",
"CustRID": "data[0].10.value",
"SerialNumber": "data[0].11.value",
"Room": "data[0].12.value",
"Datacenter": "data[0].13.value",
"UMountingID": "data[0].14.value",
"CabinetAssetID": "data[0].15.value",
"CabinetName": "data[0].16.value",
"#table1": "to" // 将静态值 "table1" 映射到 "to" 键
}
},
{
"operation": "default",
"spec": {
"fieldsToReturn": [6, 7, 8, 9, 10, 11, 12] // 添加静态数组
}
},
{
"operation": "sort" // 可选:对输出对象进行排序
}
]使用此 Spec 进行转换,将得到完全符合期望的输出:
{
"data" : [
{
"6" : {
"value" : "1"
},
"7" : {
"value" : "2"
},
"8" : {
"value" : "Cisco MDS 9706"
},
"9" : {
"value" : "Cisco-MDS-9706_1"
},
"10" : {
"value" : "A001"
},
"11" : {
"value" : "OU812"
},
"12" : {
"value" : "ROOM5"
},
"13" : {
"value" : "DC69"
},
"14" : {
"value" : "86"
},
"15" : {
"value" : "181"
},
"16" : {
"value" : "CAB666"
}
}
],
"to" : "table1",
"fieldsToReturn" : [ 6, 7, 8, 9, 10, 11, 12 ]
}总结
通过本教程,我们学习了在 JOLT shift 操作中,如何通过使用固定的数组索引(如 data[0])而非动态索引(data[]),来有效地将多个输入字段合并到目标数组中的单一对象。这种方法避免了生成冗余的 {} 结构,使输出 JSON 更符合预期。同时,我们还探讨了将静态值添加操作整合到 shift 阶段,以及使用 sort 操作进行输出优化的技巧,从而编写出更简洁、高效的 JOLT 转换规范。理解 JOLT 中数组索引的工作原理是实现复杂 JSON 结构转换的关键。










