You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Jolt库处理多数组嵌套循环:我的转换Spec为何失效?

Jolt转换Spec问题分析与修正

问题背景

需要将包含人员列表的JSON按合同角色分组:

  • 订阅者(SOUSCRIPTEUR)归入policies.subscribers[]
  • 被保险人(ASSURE)归入policies.insured[]
  • 共同订阅者(CO_SOUSCRIPTEUR)归入policies.cosubscribers[]
    同时生成parties列表和tickets.processId(根据订阅者是否为自然人设置%phys%或%morale%)。当前的Jolt Shift Spec无法得到预期输出,以下是问题分析和修正方案。

输入JSON

{
  "personnes": [
    {
      "refExternePersonne": "BGHT34271",
      "isPersonnePhysique": true,
      "rolesContrat": [
        "CO_SOUSCRIPTEUR",
        "ASSURE"
      ],
      "adresses": [
        {
          "typeAdresse": "RESIDENCE_SECONDAIRE"
        },
        {
          "typeAdresse": "FISCALE"
        }
      ]
    },
    {
      "refExternePersonne": "BGHT34272",
      "isPersonnePhysique": false,
      "rolesContrat": [
        "SOUSCRIPTEUR",
        "PAYEUR_PRIMES",
        "ASSURE"
      ],
      "adresses": [
        {
          "typeAdresse": "FISCALE"
        },
        {
          "typeAdresse": "CORRESPONDANCE"
        }
      ]
    }
  ]
}

当前Jolt Spec

[
  {
    "operation": "shift",
    "spec": {
      "personnes": {
        "*": {
          "refExternePersonne": "parties[&1].partyRef",
          "rolesContrat": {
            "*": {
              "SOUSCRIPTEUR": {
                "@(3,isPersonnePhysique)": {
                  "true": {
                    "#%phys%": "tickets.processId"
                  },
                  "false": {
                    "#%morale%": "tickets.processId"
                  }
                },
                "@(3,refExternePersonne)": "policies.subscribers[].partyRef",
                "@(3,idPersonne)": "policies.subscribers[].partyId",
                "@(3,adresses)": "policies.subscribers[].addressesTemp"
              },
              "CO_SOUSCRIPTEUR": {
                "@(3,refExternePersonne)": "policies.cosubscribers[].partyRef",
                "@(3,idPersonne)": "policies.cosubscribers[].partyId",
                "@(3,adresses)": "policies.cosubscribers[].addressesTemp"
              },
              "ASSURE": {
                "@(3,refExternePersonne)": "policies.insured[].partyRef",
                "@(3,idPersonne)": "policies.insured[].partyId",
                "@(3,adresses)": "policies.insured[].addressesTemp"
              }
            }
          }
        }
      }
    }
  }
]

预期输出

{
  "parties": [
    {
      "partyRef": "BGHT34271"
    },
    {
      "partyRef": "BGHT34272"
    }
  ],
  "policies": {
    "cosubscribers": [
      {
        "partyRef": "BGHT34271",
        "addressesTemp": [
          {
            "typeAdresse": "RESIDENCE_SECONDAIRE"
          },
          {
            "typeAdresse": "FISCALE"
          }
        ]
      }
    ],
    "insured": [
      {
        "partyRef": "BGHT34271",
        "addressesTemp": [
          {
            "typeAdresse": "RESIDENCE_SECONDAIRE"
          },
          {
            "typeAdresse": "FISCALE"
          }
        ]
      },
      {
        "partyRef": "BGHT34272",
        "addressesTemp": [
          {
            "typeAdresse": "FISCALE"
          },
          {
            "typeAdresse": "CORRESPONDANCE"
          }
        ]
      }
    ],
    "subscribers": [
      {
        "partyRef": "BGHT34272",
        "addressesTemp": [
          {
            "typeAdresse": "FISCALE"
          },
          {
            "typeAdresse": "CORRESPONDANCE"
          }
        ]
      }
    ]
  },
  "tickets": {
    "processId": "%morale%"
  }
}

当前Spec存在的问题

  1. 属性拆分导致数组对象异常
    遍历rolesContrat数组时,每个属性(partyRef、addressesTemp)单独使用[]写入数组,会生成多个独立对象(比如一个对象只有partyRef,另一个只有addressesTemp),而不是将所有属性合并到同一个对象中。

  2. 无效字段冗余
    输入JSON中不存在idPersonne字段,但当前Spec仍尝试映射该字段,会生成无用的null值或空字段。

  3. tickets.processId赋值逻辑缺陷
    嵌套在SOUSCRIPTEUR角色的遍历逻辑中,若存在多个订阅者,后续值会覆盖之前的赋值;同时遍历数组时可能触发多次赋值,最终结果取决于最后一次遍历的值。

  4. 角色匹配时的数组索引问题
    未确保同一人员的属性被写入同一个数组元素,逻辑上存在重复生成对象的隐患。

修正后的Jolt Spec

[
  {
    "operation": "shift",
    "spec": {
      "personnes": {
        "*": {
          // 生成parties列表
          "refExternePersonne": "parties[&1].partyRef",
          // 处理订阅者的processId:基于订阅者身份设置值
          "rolesContrat": {
            "*": {
              "SOUSCRIPTEUR": {
                "@(2,isPersonnePhysique)": {
                  "true": { "#%phys%": "tickets.processId" },
                  "false": { "#%morale%": "tickets.processId" }
                }
              }
            }
          },
          // 根据角色分组,将当前人员的属性映射到对应数组的同一个对象中
          "@": {
            "rolesContrat": {
              "SOUSCRIPTEUR": {
                "@2,refExternePersonne": "policies.subscribers[-1].partyRef",
                "@2,adresses": "policies.subscribers[-1].addressesTemp"
              },
              "CO_SOUSCRIPTEUR": {
                "@2,refExternePersonne": "policies.cosubscribers[-1].partyRef",
                "@2,adresses": "policies.cosubscribers[-1].addressesTemp"
              },
              "ASSURE": {
                "@2,refExternePersonne": "policies.insured[-1].partyRef",
                "@2,adresses": "policies.insured[-1].addressesTemp"
              }
            }
          }
        }
      }
    }
  }
]

修正说明

  • 使用@引用当前人员对象,结合角色匹配,将partyRef和addressesTemp写入同一个数组元素([-1]表示追加到数组末尾的当前元素),确保属性合并为一个对象。
  • 移除了无效的idPersonne映射,符合预期输出要求。
  • 调整tickets.processId的赋值逻辑,确保基于订阅者的身份正确设置值,避免多次覆盖的问题。
  • 保留原parties列表的生成逻辑,该逻辑本身是正确的。

内容的提问来源于stack exchange,提问作者gbouget

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 01:45:09