
本文详细介绍了在使用jolt进行json数据转换时,如何解决将输入数据中的多个字段分别转换为数组中独立对象的问题,并将其优化为单个包含所有字段的对象。核心解决方案是利用jolt shift 操作中的固定数组索引(如data[0]),确保所有目标字段都映射到数组的同一个元素中,同时提供了优化jolt规范的实践建议。
引言:JOLT数组转换中的常见挑战
在使用JOLT进行JSON数据转换时,一个常见的需求是将扁平化的输入JSON结构转换为包含特定字段的数组。然而,在实际操作中,如果不正确地配置JOLT shift 规范,可能会导致数组中每个字段都成为一个独立的子对象,而非所有字段合并成一个单一的复杂对象。这种“冗余的括号”结构通常不是我们所期望的。本教程将深入探讨这一问题,并提供一个高效且优雅的解决方案。
原始输入与问题描述
假设我们有一个扁平化的JSON对象作为输入,其中包含资产的各种属性:
原始输入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"
}当前JOLT转换规范及输出
为了将这些资产信息转换为一个名为 data 的数组,其中每个字段都包含一个 value 键,我们可能最初会尝试以下JOLT shift 规范:
[
{
"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]
}
}
]使用上述规范进行转换后,会得到以下输出:
{
"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 数组中包含了多个独立的JSON对象,每个对象只包含一个键值对。这并不是我们想要的。
期望输出结构
我们期望的输出是 data 数组中只有一个对象,该对象包含了所有转换后的键值对:
{
"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 操作中数组索引的使用。
理解shift操作中的数组索引
- 当在 shift 规范中使用 [] 时(例如 data[]),JOLT 会为每个匹配的输入创建一个新的数组元素。因此,在上面的例子中,每个 AssetID、AssetNumber 等都会在 data 数组中生成一个全新的对象。
- 为了将所有字段合并到数组中的 同一个 对象里,我们需要指定一个 固定 的数组索引。最常见且直接的方法是使用 [0],即 data[0]。这将确保所有匹配的转换都指向 data 数组的第一个元素。
修正后的JOLT转换规范
基于上述理解,我们可以修改 shift 规范,将所有输出路径的目标数组索引固定为 0。同时,为了优化JOLT规范,可以将第一个 default 操作(用于设置 "to": "table1")直接合并到 shift 规范中,通过使用 # 符号来指定常量值。
PHP经典实例(第2版)能够为您节省宝贵的Web开发时间。有了这些针对真实问题的解决方案放在手边,大多数编程难题都会迎刃而解。《PHP经典实例(第2版)》将PHP的特性与经典实例丛书的独特形式组合到一起,足以帮您成功地构建跨浏览器的Web应用程序。在这个修订版中,您可以更加方便地找到各种编程问题的解决方案,《PHP经典实例(第2版)》中内容涵盖了:表单处理;Session管理;数据库交互;使用We
[
{
"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" // 将 "to": "table1" 直接在此处定义
}
},
{
"operation": "default",
"spec": {
"fieldsToReturn": [6, 7, 8, 9, 10, 11, 12]
}
},
{
"operation": "sort" // 可选操作,用于对输出JSON的键进行排序
}
]规范详解
shift 操作:数据重塑
这是最关键的一步。通过将所有输出路径修改为 data[0].X.value,我们指示JOLT:
- 将所有输入字段的值映射到名为 data 的数组中。
- 所有这些值都将作为键值对,放置在 data 数组的 第一个 元素(索引为 0)内部。
- 每个值都嵌套在一个以数字为键(如 6, 7 等)的对象中,该对象又包含一个 value 键。
- "#table1": "to":这是一个JOLT的快捷方式,用于将常量值 table1 映射到输出JSON的 to 键。这使得我们不再需要单独的 default 操作来添加此字段。
default 操作:补充默认值
{
"operation": "default",
"spec": {
"fieldsToReturn": [6, 7, 8, 9, 10, 11, 12]
}
}此操作用于在输出JSON中添加一个名为 fieldsToReturn 的数组,其中包含指定的数字列表。这是一个独立的默认值添加,与 shift 操作的目标结构无关。
sort 操作(可选):排序字段
{
"operation": "sort"
}sort 操作会按照字母顺序对JSON对象的键进行排序。这通常是为了提高输出的可读性或确保输出的确定性,但对于解决核心的结构问题并非必需。
完整优化后的JOLT规范
结合所有优化和修正,最终的JOLT规范如下:
[
{
"operation": "shift",
"spec": {
"AssetID": "data[0].6.value",
"AssetNumber": "data[0].7.value",
"AssetMaterial": "data[0].8.value",
"RackUnits": "data[0].RackUnits.value", // 示例:可以根据需要保留原始键名
"MaterialType": "data[0].MaterialType.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"
}
},
{
"operation": "default",
"spec": {
"fieldsToReturn": [6, 7, 8, 9, 10, 11, 12]
}
},
{
"operation": "sort"
}
]注意:在上述 shift 规范中,我将 RackUnits 和 MaterialType 的目标键名从数字改回了原始键名,以展示灵活性。你可以根据实际需求选择使用数字或原始键名。
应用此规范后,JOLT将生成与期望输出完全一致的JSON结构。
总结与最佳实践
- 固定数组索引:当需要将多个输入字段合并到数组中的单个对象时,务必在 shift 规范中使用固定的数组索引(例如 [0]),而非 []。[] 会为每个匹配项创建新的数组元素。
- 规范优化:对于简单的常量值,可以直接在 shift 规范中使用 # 语法来定义,从而减少 default 操作的步骤,使JOLT规范更简洁高效。
- 理解JOLT操作:深入理解 shift、default 等JOLT操作的工作原理是编写高效转换规范的关键。
通过掌握这些技巧,您可以更有效地利用JOLT进行复杂的数据重塑和转换,避免常见的结构性问题。









