基于JOLT构建复杂嵌套JSON对象的技术求助
求助:JOLT中为嵌套JSON数组的所有对象统一添加同一JobId值
我现在在尝试用JOLT构建一个复杂的嵌套JSON对象数组,但始终得不到想要的结构,卡在这里了。我之前看JOLT官网的递归迭代内容,但这个概念有点绕,没太搞明白。我的核心需求是:不管数组里有多少个对象(哪怕上千个),所有对象里的JobId必须是同一个毫秒值,所以我只想生成一次这个值,但就是没法把它放到所有需要的位置上。麻烦各位帮忙看看!
输入JSON
{ "type": "FeatureCollection", "totalFeatures": 2, "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 13.429916995511855, 52.54516530881942 ] }, "properties": { "feature_type": "BLDG", "feature_geometry": "point", "discipline": "LOC", "activity": "AC", "be_number": 12313, "category": 47400, "condition": "RDY", "review_date": "2018-03-28T21:36:32.325Z", "role_type": "INSG", "symbol_code": "-" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 16.429916995511855, 91.54516530881942 ] }, "properties": { "feature_type": "Bridge", "feature_geometry": "point", "discipline": "LOC", "activity": "AC", "co_number": 12313, "category": 47400, "condition": "RDY", "review_date": "2018-03-28T21:36:32.325Z", "role_type": "KLDV", "symbol_code": "-" } } ] }
当前使用的JOLT规则
[{ "operation": "shift", "spec": { "type": "type", "features": { "*": { "geometry": { "coordinates": { "0": "FacilityComposite[&3].Facility.Ilat", "1": "FacilityComposite[&3].Facility.Ilon" } }, "properties": { "activity": "FacilityComposite[&2].Facility.Activity", "be_number": "FacilityComposite[&2].Facility.BeNumber", "category": "FacilityComposite[&2].Facility.Category", "condition": "FacilityComposite[&2].Facility.Condition", "role_type": ["FacilityComposite[&2].Facility.RoleType", "FacilityComposite[&2].FacForm.RoleType", "FacilityComposite[&2].FacTie[&2].RoleType"], "review_date": ["FacilityComposite[&2].Facility.ReviewDate", "FacilityComposite[&2].FacForm.ReviewDate", "FacilityComposite[&2].FacTie[&2].ReviewDate"] } } } } }, { "operation": "default", "spec": { "JobId": "${now():toNumber()}", "FacilityComposite[]": { "*": { "Facility": { "FacSk": "-1", "ClientId": "DISHNET", "ReviewDate": "${now()}" }, "FacForm": { "FacSk": "-1", "ClientId": "DISHNET" }, "FacTie": [{ "FacTieSk": "-1", "TieFromSk": "-1", "TieToSk": "-1", "ClientId": "DISHNET" }] } } } } ]
当前规则生成的输出
{ "type" : "FeatureCollection", "FacilityComposite" : [ { "Facility" : { "Ilat" : 13.429916995511855, "Ilon" : 52.54516530881942, "Activity" : "AC", "BeNumber" : 12313, "Category" : 47400, "Condition" : "RDY", "RoleType" : "INSG", "ReviewDate" : "2018-03-28T21:36:32.325Z", "ClientId" : "DISHNET", "FacSk" : "-1" }, "FacForm" : { "RoleType" : "INSG", "ReviewDate" : "2018-03-28T21:36:32.325Z", "FacSk" : "-1", "ClientId" : "DISHNET" }, "FacTie" : [ { "RoleType" : "INSG", "ReviewDate" : "2018-03-28T21:36:32.325Z" } ] }, { "Facility" : { "Ilat" : 16.429916995511856, "Ilon" : 91.54516530881942, "Activity" : "AC", "Category" : 47400, "Condition" : "RDY", "RoleType" : "KLDV", "ReviewDate" : "2018-03-28T21:36:32.325Z", "ClientId" : "DISHNET", "FacSk" : "-1" }, "FacForm" : { "RoleType" : "KLDV", "ReviewDate" : "2018-03-28T21:36:32.325Z", "FacSk" : "-1", "ClientId" : "DISHNET" }, "FacTie" : [ null, { "RoleType" : "KLDV", "ReviewDate" : "2018-03-28T21:36:32.325Z" } ] } ], "JobId" : "${now():toNumber()}" }
预期输出
{ "type" : "FeatureCollection", "FacilityComposite" : [ { "Facility" : { "JobId" : "${now():toNumber()}", "Ilat" : 13.429916995511855, "Ilon" : 52.54516530881942, "Activity" : "AC", "BeNumber" : 12313, "Category" : 47400, "Condition" : "RDY", "RoleType" : "INSG", "ReviewDate" : "2018-03-28T21:36:32.325Z", "ClientId" : "DISHNET", "FacSk" : "-1" }, "FacForm" : { "JobId" : "${now():toNumber()}", "RoleType" : "INSG", "ReviewDate" : "2018-03-28T21:36:32.325Z", "FacSk" : "-1", "ClientId" : "DISHNET" }, "FacTie" : [ { "FacTieSk": "-1", "TieFromSk": "-1", "TieToSk": "-1", "JobId" : "${now():toNumber()}", "ClientId": "DISHNET", "RoleType" : "INSG", "ReviewDate" : "2018-03-28T21:36:32.325Z" } ] }, { "Facility" : { "JobId" : "${now():toNumber()}", "Ilat" : 16.429916995511856, "Ilon" : 91.54516530881942, "Activity" : "AC", "Category" : 47400, "Condition" : "RDY", "RoleType" : "KLDV", "ReviewDate" : "2018-03-28T21:36:32.325Z", "ClientId" : "DISHNET", "FacSk" : "-1" }, "FacForm" : { "JobId" : "${now():toNumber()}", "RoleType" : "KLDV", "ReviewDate" : "2018-03-28T21:36:32.325Z", "FacSk" : "-1", "ClientId" : "DISHNET" }, "FacTie" : [ { "FacTieSk": "-1", "TieFromSk": "-1", "TieToSk": "-1", "JobId" : "${now():toNumber()}", "ClientId": "DISHNET", "RoleType" : "KLDV", "ReviewDate" : "2018-03-28T21:36:32.325Z" } ] } ] }
解决方案
你的核心问题是需要把顶层生成的同一个JobId值,传递到嵌套的每个对象里,同时还要修正当前规则里的一些小问题(比如FacTie数组的索引错误导致的null值)。这里给你调整后的JOLT规则:
[ // 第一步:先在顶层生成唯一的JobId,确保整个转换过程中值固定 { "operation": "modify-default-beta", "spec": { "JobId": "${now():toNumber()}" } }, // 第二步:完成结构映射,同时将顶层JobId传递到所有需要的嵌套位置 { "operation": "shift", "spec": { "type": "type", "JobId": "JobId", // 可选:保留顶层JobId,不需要的话可以删除这一行 "features": { "*": { "geometry": { "coordinates": { "0": "FacilityComposite[&3].Facility.Ilat", "1": "FacilityComposite[&3].Facility.Ilon" } }, "properties": { "activity": "FacilityComposite[&2].Facility.Activity", "be_number": "FacilityComposite[&2].Facility.BeNumber", "category": "FacilityComposite[&2].Facility.Category", "condition": "FacilityComposite[&2].Facility.Condition", "role_type": [ "FacilityComposite[&2].Facility.RoleType", "FacilityComposite[&2].FacForm.RoleType", "FacilityComposite[&2].FacTie[0].RoleType" // 修正索引:每个FacTie只有一个元素,用[0]避免null ], "review_date": [ "FacilityComposite[&2].Facility.ReviewDate", "FacilityComposite[&2].FacForm.ReviewDate", "FacilityComposite[&2].FacTie[0].ReviewDate" // 同样修正索引 ] }, // 引用顶层的JobId,传递到当前Feature对应的三个嵌套对象中 "@(2,JobId)": [ "FacilityComposite[&1].Facility.JobId", "FacilityComposite[&1].FacForm.JobId", "FacilityComposite[&1].FacTie[0].JobId" ] } } } }, // 第三步:添加默认值,注意不再重复生成JobId { "operation": "default", "spec": { "FacilityComposite[]": { "*": { "Facility": { "FacSk": "-1", "ClientId": "DISHNET" // 移除了ReviewDate的默认设置,避免覆盖输入中的原始日期 }, "FacForm": { "FacSk": "-1", "ClientId": "DISHNET" }, "FacTie": [ { "FacTieSk": "-1", "TieFromSk": "-1", "TieToSk": "-1", "ClientId": "DISHNET" } ] } } } } ]
关键调整说明
- 固定JobId生成时机:用
modify-default-beta提前在顶层生成一次JobId,确保整个转换过程中这个值是唯一且不变的,不会因为多次生成导致不一致。 - 传递JobId到嵌套对象:在
shift操作中,通过@(2,JobId)引用顶层的JobId值,将其映射到Facility、FacForm、FacTie[0]三个需要的位置,保证所有对象使用同一个值。 - 修正FacTie数组索引:原来的
FacTie[&2]会导致第二个Feature的FacTie数组出现null值,改成FacTie[0]后,每个Feature的FacTie数组只会有一个元素,结构更符合预期。 - 避免覆盖原始数据:移除了默认规则中对
Facility.ReviewDate的设置,保留输入中的原始日期值,不会被当前时间覆盖。
这样调整后,就能得到你想要的结构,所有嵌套对象里的JobId都会是同一个毫秒值,同时也解决了之前的结构错误问题。
内容的提问来源于stack exchange,提问作者user1997772
相关产品推荐
相关产品推荐

