如何在NiFi的Jolt Spec中处理Null值?配置失效问题解决
问题描述
给定的CSV数据已转为JSON格式,现有Jolt转换规范未处理Null值场景,需满足以下要求:
- 若
Sub-Model1为Null,至少保留到Model1层级; - 若
Model1为Null,则保留到Company层级(如Agent A3的场景)。
原始数据(CSV转JSON)
[ { "Agent": "A1", "Location": "L1", "Company": "Hyundai", "Model1": "Verna", "Sub-Model1": "2018" }, { "Agent": "A1", "Location": "L1", "Company": "Hyundai", "Model1": "Creta", "Sub-Model1": null }, { "Agent": "A1", "Location": "L1", "Company": "Hyundai", "Model1": "Aura", "Sub-Model1":null }, { "Agent": "A2", "Location": "L1", "Company": "Toyota", "Model1": "Fortuner", "Sub-Model1": "2020" }, { "Agent": "A3", "Location": "L1", "Company": "BMW", "Model1": null, "Sub-Model1": null } ]
现有Jolt转换规范
[ { "operation": "shift", "spec": { "*": { "@(0,Agent)": "@(1,Agent).Agent", "@(0,Location)": "@(1,Agent).loc_id", "Sub-Model1": "@(1,Agent).Company.@(1,Company).@(1,Model1).@(1,Sub-Model1)" } } }, { "operation": "cardinality", "spec": { "*": { // A1, A2 "loc_id": "ONE", "Agent": "ONE" } } }, { "operation": "shift", "spec": { "*": { // A1, A2 "*": "[#2].&", "Company": { "*": { // Hyundai "*": { // Verna "*": { // 2018 "@": "[#6].&4.&3[#3].&2.[#1].&" } } } } } } }, { "operation": "modify-overwrite-beta", "spec": { "*": { "*": { "*": { "*": { "*": { "*": { "*": [] } } } } } } } } ]
当前转换输出
仅保留了Verna、Fortuner的完整层级,Creta、Aura及BMW的数据未正确输出,丢失了可用信息:
[ { "Agent": "A1", "loc_id": "L1", "Company": { "Hyundai": [ { "Verna": [ { "2018": [] } ] } ] } }, { "Agent": "A2", "loc_id": "L1", "Company": { "Toyota": [ { "Fortuner": [ { "2020": [] } ] } ] } }, { "Agent": "A3", "loc_id": "L1" } ]
期望输出
保留所有可用数据层级,即使存在Null值:
[ { "Agent": "A1", "loc_id": "L1", "Company": { "Hyundai": [ { "Verna": [ { "2018": [] } ] }, { "Creta": [ {} ] }, { "Aura": [ {} ] } ] } }, { "Agent": "A2", "loc_id": "L1", "Company": { "Toyota": [ { "Fortuner": [ { "2020": [] } ] } ] } }, { "Agent": "A3", "loc_id": "L1", "Company": { "BMW": [ {} ] } } ]
修正后的Jolt转换规范
[ { "operation": "shift", "spec": { "*": { "@(0,Agent)": "@(1,Agent).Agent", "@(0,Location)": "@(1,Agent).loc_id", // 处理Sub-Model1非空的完整层级 "Sub-Model1": { "?": { "@2,Company": "@3,Agent.Company.@2,Company.[#2].@2,Model1.[#2].&" } }, // 处理Sub-Model1为空但Model1非空的场景 "Model1": { "?": { "@2,Company": "@3,Agent.Company.@2,Company.[#2].&" } }, // 处理Model1为空的Company层级场景 "Company": { "*": { "@": "@3,Agent.Company.&.[#2]" } } } } }, { "operation": "cardinality", "spec": { "*": { "loc_id": "ONE", "Agent": "ONE" } } }, { "operation": "shift", "spec": { "*": { "*": "[#2].&", "Company": { "*": { // 聚合Sub-Model1层级的数据 "*": { "*": { "*": { "@": "[#6].&4.&3[#3].&2.[#1].&" } }, // 聚合仅Model1层级的数据 "$": "[#5].&3.&2[#2].&" }, // 聚合仅Company层级的数据 "$": "[#4].&2.[#1]" } } } } }, { "operation": "modify-overwrite-beta", "spec": { "*": { "Company": { "*": { "*": { "*": { "*": [] }, // 为仅Model1层级的条目补全空数组 "$": "[]" }, // 为仅Company层级的条目补全空对象数组 "$": "[{}]" } } } } } ]
关键修改说明
- 多场景分支处理:第一个shift操作分三个分支覆盖所有Null值场景,确保每个可用层级都能被保留;
- 层级聚合调整:第二个shift操作优化了路径匹配逻辑,确保同一Agent下的同层级数据被正确聚合为数组;
- 空结构补全:modify操作针对不同层级的空场景,补全了对应的空数组或空对象,完全匹配期望输出的结构。
内容的提问来源于stack exchange,提问作者Destiel
相关产品推荐
相关产品推荐

