NiFi中基于JsonPath从指定Json提取值填充目标Json的方案咨询
实现JSON路径替换的方案建议
核心需求是:遍历目标JSON(Json2)中的value字段,若字段值是源JSON(Json1)的合法JsonPath,则用源JSON对应路径的值替换该字段,否则保留原值。以下是几种不同场景下的实现方案:
Python 实现
依赖第三方库jsonpath-ng处理JsonPath解析,步骤如下:
- 安装依赖库:
pip install jsonpath-ng json
- 实现代码:
import json from jsonpath_ng import parse # 解析两个JSON(可直接传入字符串,或从文件读取) json1 = json.loads("""{ "level_1": [ { "level_2_1": [ { "key_2_1": "value_1", "key_2_2": "value_2" }, { "key_2_1": "value_1", "key_2_3": "value_3" }, { "key_2_1": "value_1", "key_2_4": "value_4" } ], "level_2_2": { "key_2_2_1": "2022-08-30T06:57:31.331Z", "key_2_2_2": "2022" } } ] }""") json2 = json.loads("""{ "level_1" : { "level_2_1" : { "value" : "default value", "type" : "String" }, "level_2_2" : { "value" : "level_1[0].level_2_1[0].key_2_2", "type" : "String" }, "level_2_3" : { "value" : "level_1[0].level_2_2.key_2_2_1", "type" : "String" } } }""") def replace_jsonpath(obj, source_json): """递归遍历对象,替换符合条件的value字段""" if isinstance(obj, dict): for key, value in obj.items(): if key == "value": try: jsonpath_expr = parse(value) match = jsonpath_expr.find(source_json) if match: obj[key] = match[0].value except Exception: # 解析失败,保留原值 pass else: replace_jsonpath(value, source_json) elif isinstance(obj, list): for item in obj: replace_jsonpath(item, source_json) return obj # 执行替换并输出结果 result = replace_jsonpath(json2, json1) print(json.dumps(result, indent=2))
Java 实现
使用Jayway JsonPath库处理路径解析,步骤如下:
- 引入Maven依赖:
<dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency>
- 实现代码:
import com.jayway.jsonpath.JsonPath; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; public class JsonPathReplacer { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 加载源JSON和目标JSON String json1Str = "{\"level_1\":[{\"level_2_1\":[{\"key_2_1\":\"value_1\",\"key_2_2\":\"value_2\"},{\"key_2_1\":\"value_1\",\"key_2_3\":\"value_3\"},{\"key_2_1\":\"value_1\",\"key_2_4\":\"value_4\"}],\"level_2_2\":{\"key_2_2_1\":\"2022-08-30T06:57:31.331Z\",\"key_2_2_2\":\"2022\"}}]}"; String json2Str = "{\"level_1\":{\"level_2_1\":{\"value\":\"default value\",\"type\":\"String\"},\"level_2_2\":{\"value\":\"level_1[0].level_2_1[0].key_2_2\",\"type\":\"String\"},\"level_2_3\":{\"value\":\"level_1[0].level_2_2.key_2_2_1\",\"type\":\"String\"}}}"; JsonNode json1 = mapper.readTree(json1Str); JsonNode json2 = mapper.readTree(json2Str); replaceValues((ObjectNode) json2, json1); // 输出格式化后的结果 System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json2)); } private static void replaceValues(ObjectNode node, JsonNode source) { for (String key : node.fieldNames()) { JsonNode child = node.get(key); if (child.isObject()) { if (child.has("value") && child.get("value").isTextual()) { String path = child.get("value").asText(); try { Object value = JsonPath.read(source, path); ((ObjectNode) child).put("value", value.toString()); } catch (Exception e) { // 路径无效,保留原值 } } else { replaceValues((ObjectNode) child, source); } } else if (child.isArray()) { for (int i = 0; i < child.size(); i++) { if (child.get(i).isObject()) { replaceValues((ObjectNode) child.get(i), source); } } } } } }
命令行工具 jq 实现
jq支持类JsonPath的查询语法,可通过脚本实现替换:
# 假设json1和json2内容分别存入json1.json和json2.json文件,执行以下命令 jq --argfile src json1.json ' def replace_value($src): if .value | test("^level_1\\[.*\\]") then .value = ($src | getpath($.value | split(".") | map( if test("^\\[.*\\]$") then .[1:-1] | tonumber else . end ))) else . end; walk(if type == "object" and has("value") then replace_value($src) else . end) ' json2.json
脚本会遍历Json2的所有对象,若包含value字段且值符合JsonPath格式,就转换为jq的getpath参数,从源JSON中取值替换。
内容的提问来源于stack exchange,提问作者mycuser
相关产品推荐
相关产品推荐

