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

如何使用JsonPath动态创建路径并设置未存在的文档字段?

解决JsonPath设置不存在字段时自动创建中间节点的问题

默认情况下,JsonPath的set方法不会自动创建路径中缺失的中间节点,直接对空文档执行doc.set(JsonPath.compile("$.some.array[0].value"), "abc")会失败。要实现需求,你可以手动解析JsonPath的路径分段(令牌),遍历并创建缺失的节点结构,再执行set操作。

实现步骤

  1. 编译目标JsonPath,获取路径的各个分段信息;
  2. 从根文档开始,逐个遍历路径分段(跳过最后一个要设置的字段);
  3. 根据分段类型(属性节点/数组索引节点),创建对应的空结构(Map或List);
  4. 完成中间节点创建后,再调用set方法设置目标值。

代码实现

工具类:自动创建缺失节点

import com.jayway.jsonpath.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonPathNodeCreator {
    public static void createMissingNodes(Object document, String jsonPath) {
        CompiledJsonPath compiledPath = JsonPath.compile(jsonPath);
        Path path = compiledPath.getRootPath();
        Object currentNode = document;

        // 遍历路径的前n-1个分段,最后一个是要赋值的字段,无需提前创建
        for (int i = 0; i < path.getSegments().size() - 1; i++) {
            Segment segment = path.getSegments().get(i);
            if (segment.isArraySegment()) {
                handleArraySegment(currentNode, (ArraySegment) segment, path.getSegments().get(i + 1));
                currentNode = getCurrentArrayNode(currentNode, segment);
            } else {
                handleObjectSegment(currentNode, segment, path.getSegments().get(i + 1));
                currentNode = ((Map<String, Object>) currentNode).get(segment.getPathFragment());
            }
        }
    }

    private static void handleArraySegment(Object parentNode, ArraySegment arraySegment, Segment nextSegment) {
        Map<String, Object> parentMap = (Map<String, Object>) parentNode;
        String arrayKey = arraySegment.getPathFragment();
        int index = arraySegment.getIndex();

        // 如果父节点中没有该数组,创建空列表
        if (!parentMap.containsKey(arrayKey)) {
            parentMap.put(arrayKey, new ArrayList<>());
        }

        List<Object> array = (List<Object>) parentMap.get(arrayKey);
        // 确保列表长度足够容纳目标索引,不足则填充空对象(根据下一个节点类型决定是Map还是List)
        while (array.size() <= index) {
            Object emptyNode = nextSegment.isArraySegment() ? new ArrayList<>() : new HashMap<>();
            array.add(emptyNode);
        }
    }

    private static void handleObjectSegment(Object parentNode, Segment segment, Segment nextSegment) {
        Map<String, Object> parentMap = (Map<String, Object>) parentNode;
        String key = segment.getPathFragment();

        // 如果父节点中没有该属性,创建对应的空结构(下一个是数组则创建List,否则创建Map)
        if (!parentMap.containsKey(key)) {
            Object emptyNode = nextSegment.isArraySegment() ? new ArrayList<>() : new HashMap<>();
            parentMap.put(key, emptyNode);
        }
    }

    private static Object getCurrentArrayNode(Object parentNode, Segment segment) {
        Map<String, Object> parentMap = (Map<String, Object>) parentNode;
        List<Object> array = (List<Object>) parentMap.get(segment.getPathFragment());
        ArraySegment arraySegment = (ArraySegment) segment;
        return array.get(arraySegment.getIndex());
    }
}

使用示例

import com.jayway.jsonpath.JsonPath;
import java.util.HashMap;
import java.util.Map;

public class Demo {
    public static void main(String[] args) {
        // 空文档
        Map<String, Object> doc = new HashMap<>();
        String targetPath = "$.some.array[0].value";
        String targetValue = "abc";

        // 先创建缺失的中间节点
        JsonPathNodeCreator.createMissingNodes(doc, targetPath);
        // 再设置目标值
        JsonPath.parse(doc).set(targetPath, targetValue);

        // 输出结果
        System.out.println(JsonPath.parse(doc).jsonString());
    }
}

说明

  • 该工具类会根据路径分段的类型(属性/数组),自动创建对应的中间结构;
  • 针对数组索引,会自动填充空对象直到满足目标索引的长度要求;
  • 注意适配你使用的JsonPath版本,部分版本的API可能略有差异(比如getRootPath()在旧版本中可能为getPath())。

内容的提问来源于stack exchange,提问作者Mauricio Burgos Herrera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:05:18