如何在Java中修改包含多组键值对的JSON数据
Java场景下灵活修改JSON键值对的实现方案
Java生态没有内置JSON处理能力,不需要手动做字符串拼接/替换修改JSON(这种方式遇到转义字符、嵌套同名字段极容易出bug),直接使用成熟的第三方JSON类库,就可以实现任意层级、任意类型键值对的灵活调整,生产环境常用方案如下:
方案1:Jackson(Spring生态默认集成,通用性最强)
SpringBoot项目默认已经集成Jackson,不需要额外引入依赖;普通Java项目只需要引入对应依赖即可使用。核心是通过ObjectMapper将JSON字符串解析为可编辑的节点树,直接操作节点完成值修改,支持所有JSON数据类型。
示例代码:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; public class JacksonJsonEdit { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); // 原始多键值对JSON数据,包含顶层字段、嵌套对象、数组结构 String rawJson = "{\"name\":\"张三\",\"age\":25,\"isVip\":false,\"address\":{\"city\":\"北京\",\"street\":\"朝阳路\"},\"hobbies\":[\"篮球\",\"读书\"]}"; // 解析为可修改的根节点 ObjectNode root = (ObjectNode) objectMapper.readTree(rawJson); // 修改顶层普通键值对,支持字符串、数字、布尔、null任意类型 root.put("age", 26); root.put("isVip", true); root.putNull("tempMark"); // 新增不存在的键值对 root.put("gender", "男"); // 删除指定键 root.remove("tempMark"); // 修改嵌套对象内的value ObjectNode addressNode = (ObjectNode) root.get("address"); addressNode.put("street", "建国路"); // 修改数组内的元素值 ArrayNode hobbiesNode = (ArrayNode) root.get("hobbies"); hobbiesNode.set(0, new TextNode("足球")); // 转换回JSON字符串 String modifiedJson = objectMapper.writeValueAsString(root); System.out.println(modifiedJson); } }
方案2:Fastjson2(API简洁,性能优异)
Fastjson2是Fastjson1.x的安全重构版本,API设计直白,支持JSONPath直接定位深层节点,适合需要快速操作、JSON层级较深的场景,注意不要使用存在安全漏洞的Fastjson1.x版本。
示例代码:
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONPath; public class Fastjson2Edit { public static void main(String[] args) { String rawJson = "{\"name\":\"张三\",\"age\":25,\"address\":{\"city\":\"北京\",\"street\":\"朝阳路\"},\"hobbies\":[\"篮球\",\"读书\"]}"; JSONObject root = JSON.parseObject(rawJson); // 顶层键值对修改 root.put("age", 26); // 嵌套对象值修改 root.getJSONObject("address").put("street", "建国路"); // 数组值修改 JSONArray hobbies = root.getJSONArray("hobbies"); hobbies.set(0, "足球"); // 支持链式操作 root.fluentPut("gender", "男").fluentRemove("unusedKey"); // 深层节点可以直接用JSONPath定位修改,不需要逐层遍历 JSONPath.set(root, "$.address.city", "上海"); String modifiedJson = root.toJSONString(); } }
方案3:Gson(谷歌出品,复杂类型适配友好)
如果项目本身用Gson做序列化反序列化,可以直接用Gson的节点API完成修改,对泛型、自定义序列化逻辑的兼容性更好。
示例代码:
import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class GsonEdit { public static void main(String[] args) { Gson gson = new Gson(); String rawJson = "{\"name\":\"张三\",\"age\":25,\"address\":{\"city\":\"北京\",\"street\":\"朝阳路\"},\"hobbies\":[\"篮球\",\"读书\"]}"; JsonObject root = JsonParser.parseString(rawJson).getAsJsonObject(); // 顶层值修改 root.addProperty("age", 26); // 嵌套对象修改 root.getAsJsonObject("address").addProperty("street", "建国路"); // 数组值修改 JsonArray hobbies = root.getAsJsonArray("hobbies"); hobbies.set(0, gson.toJsonTree("足球")); String modifiedJson = gson.toJson(root); } }
通用避坑提示
- 绝对不要用字符串替换、正则匹配的方式修改JSON内容,遇到特殊字符转义、嵌套同名字段、值内容和键名重合的场景必然出现解析错误
- 操作嵌套节点、数组元素前一定要做非空判断,避免目标键不存在时触发空指针
- 类库选择尽量和项目现有JSON依赖保持一致,不要同时引入多个JSON处理包,避免类冲突、序列化规则不一致的问题
- 批量修改深层节点时优先用JSONPath表达式定位,比手动逐层遍历节点代码更简洁、出错概率更低
内容的提问来源于stack exchange,提问作者Daksh
相关产品推荐
相关产品推荐

