如何在Java中通过JsonPath用自定义函数设置嵌套JSON对象的值
解决方案:用自定义函数处理JsonPath匹配值并回写JSON
一、使用支持该功能的第三方库:Jayway JsonPath
Jayway JsonPath是Java生态中功能更丰富的JsonPath实现,原生支持通过自定义函数对匹配到的值进行转换并回写。
示例代码
首先引入Maven依赖:
<dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.8.0</version> </dependency>
然后编写处理逻辑:
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.MapFunction; import net.minidev.json.JSONObject; public class JsonPathProcessor { public static void main(String[] args) { String json = "{\n" + " \"store\": {\n" + " \"name\": \"ABC Co\",\n" + " \"book\": [\n" + " {\n" + " \"category\": \"reference\",\n" + " \"author\": \"Nigel Rees\",\n" + " \"title\": \"Sayings of the Century\",\n" + " \"price\": 8.95,\n" + " \"edition\": {\n" + " \"year\": 1990,\n" + " \"published_by\": \"MacMillan\"\n" + " }\n" + " },\n" + " {\n" + " \"category\": \"fiction\",\n" + " \"author\": \"Evelyn Waugh\",\n" + " \"title\": \"Sword of Honour\",\n" + " \"price\": 12.99,\n" + " \"edition\": {\n" + " \"year\": 1980,\n" + " \"published_by\": \"MacMillan\"\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}"; // 批量处理数组中所有书籍价格:自定义逻辑为价格加10 JSONObject modifiedJson = JsonPath.parse(json) .map("$.store.book[*].price", new MapFunction<Double, Double>() { @Override public Double map(Double currentValue, Configuration configuration) { return currentValue + 10; // 替换为你的加密/自定义处理逻辑 } }) // 处理单个对象属性:商店名称添加后缀 .map("$.store.name", new MapFunction<String, String>() { @Override public String map(String currentValue, Configuration configuration) { return currentValue + " - Updated"; } }) .json(); System.out.println(modifiedJson.toJSONString()); } }
核心说明
map方法会自动遍历所有匹配JsonPath的节点,将每个节点值传入自定义MapFunction,用返回值直接替换原节点内容。- 同时支持数组批量元素和单个对象属性的处理,完全覆盖你的需求场景。
二、基于fastjson2自行实现setNestedJson方法
如果不想切换库,可以基于fastjson2的API,先查询所有匹配节点的具体路径,再逐个应用函数并回写。
实现思路
- 用
JSONPath.eval获取所有匹配的值,同时用JSONPath.getPaths获取每个值对应的完整定位路径。 - 对每个值应用自定义函数生成新值。
- 用
JSONPath.set逐个将新值写回原JSON对象。
示例代码
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONPath; import java.util.List; import java.util.function.Function; public class FastJson2CustomProcessor { public static <T, R> void setNestedJson(JSONObject jsonObject, String jsonPath, Function<T, R> func) { // 获取所有匹配节点的值和对应路径 List<Object> matches = JSONPath.eval(jsonObject, jsonPath); List<String> nodePaths = JSONPath.getPaths(jsonObject, jsonPath); // 遍历处理每个节点 for (int i = 0; i < matches.size(); i++) { String path = nodePaths.get(i); T originalValue = (T) matches.get(i); R newValue = func.apply(originalValue); JSONPath.set(jsonObject, path, newValue); } } public static void main(String[] args) { String jsonStr = "{\n" + " \"store\": {\n" + " \"name\": \"ABC Co\",\n" + " \"book\": [\n" + " {\n" + " \"category\": \"reference\",\n" + " \"author\": \"Nigel Rees\",\n" + " \"title\": \"Sayings of the Century\",\n" + " \"price\": 8.95,\n" + " \"edition\": {\n" + " \"year\": 1990,\n" + " \"published_by\": \"MacMillan\"\n" + " }\n" + " },\n" + " {\n" + " \"category\": \"fiction\",\n" + " \"author\": \"Evelyn Waugh\",\n" + " \"title\": \"Sword of Honour\",\n" + " \"price\": 12.99,\n" + " \"edition\": {\n" + " \"year\": 1980,\n" + " \"published_by\": \"MacMillan\"\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}"; JSONObject jsonObject = JSON.parseObject(jsonStr); // 处理价格:自定义逻辑为乘以2 setNestedJson(jsonObject, "$.store.book[0:].price", (Double price) -> price * 2); // 处理商店名称:自定义逻辑为转为大写 setNestedJson(jsonObject, "$.store.name", (String name) -> name.toUpperCase()); System.out.println(jsonObject.toJSONString()); } }
核心说明
JSONPath.getPaths会返回每个匹配节点的精确路径(比如$.store.book[0].price、$.store.book[1].price),确保能精准定位修改。- 自定义函数通过
Function<T,R>接口传入,支持任意类型的转换逻辑(加密、运算、字符串处理等)。
内容的提问来源于stack exchange,提问作者Chris Paul
相关产品推荐
相关产品推荐

