Spring Boot中JSON差异存储与默认JSON合并实现问询
Spring Boot 复杂JSON差异生成、保存与合并实现方案
一、依赖配置
首先在pom.xml中添加Jackson相关依赖,确保版本与Spring Boot自带的Jackson版本对齐:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-jsonpatch</artifactId> <version>2.15.2</version> <!-- 版本需匹配Spring Boot的Jackson版本 --> </dependency>
二、生成JsonPatch并保存差异
读取默认JSON与modifiedDefault JSON,转换为JsonNode后生成差异Patch,再序列化为JSON文件保存:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.module.jsonpatch.JsonPatch; import com.fasterxml.jackson.module.jsonpatch.JsonPatchGenerator; import java.io.File; import java.io.IOException; public class JsonPatchService { private final ObjectMapper objectMapper = new ObjectMapper(); // 生成差异Patch并保存到文件 public void generateAndSavePatch(File defaultJsonFile, File modifiedJsonFile, File patchOutputFile) throws IOException { // 读取两个JSON文件为JsonNode JsonNode defaultNode = objectMapper.readTree(defaultJsonFile); JsonNode modifiedNode = objectMapper.readTree(modifiedJsonFile); // 生成从默认到修改后的JsonPatch JsonPatchGenerator patchGenerator = new JsonPatchGenerator(defaultNode); JsonPatch patch = patchGenerator.generatePatch(modifiedNode); // 将Patch序列化为格式化JSON并保存 objectMapper.writerWithDefaultPrettyPrinter().writeValue(patchOutputFile, patch); } }
三、合并默认JSON与修改内容
提供两种合并方式,按需选择:
方式1:应用保存的JsonPatch到默认JSON
如果已保存Patch文件,直接读取并应用到默认JSON:
public JsonNode mergeDefaultWithPatch(File defaultJsonFile, File patchFile) throws IOException { JsonNode defaultNode = objectMapper.readTree(defaultJsonFile); JsonPatch patch = objectMapper.readValue(patchFile, JsonPatch.class); // 应用Patch生成合并结果 return patch.apply(defaultNode); }
方式2:直接递归合并modifiedDefault与默认JSON
针对modifiedDefault覆盖默认值的场景,自定义递归逻辑处理嵌套结构与数组:
// 递归合并:modifiedNode字段覆盖defaultNode对应字段 public JsonNode mergeJsonNodes(JsonNode defaultNode, JsonNode modifiedNode) { if (modifiedNode.isObject()) { JsonNode merged = defaultNode.deepCopy(); modifiedNode.fields().forEachRemaining(entry -> { String key = entry.getKey(); JsonNode modifiedValue = entry.getValue(); JsonNode defaultValue = merged.get(key); // 嵌套对象递归合并,其他类型直接替换 if (defaultValue != null && defaultValue.isContainerNode() && modifiedValue.isContainerNode()) { merged = merged.set(key, mergeJsonNodes(defaultValue, modifiedValue)); } else { merged = merged.set(key, modifiedValue); } }); return merged; } else if (modifiedNode.isArray()) { // 数组直接替换(如需部分元素修改,可自定义数组差异逻辑) return modifiedNode.deepCopy(); } else { // 基础类型直接替换 return modifiedNode; } } // 合并方法调用入口 public JsonNode mergeDefaultWithModified(File defaultJsonFile, File modifiedJsonFile) throws IOException { JsonNode defaultNode = objectMapper.readTree(defaultJsonFile); JsonNode modifiedNode = objectMapper.readTree(modifiedJsonFile); return mergeJsonNodes(defaultNode, modifiedNode); }
四、Spring Boot Controller整合
在GET接口中调用合并逻辑返回结果:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.databind.JsonNode; import java.io.File; import java.io.IOException; @RestController public class JsonMergeController { private final JsonPatchService patchService = new JsonPatchService(); @GetMapping("/merged-config") public JsonNode getMergedConfig() throws IOException { File defaultFile = new File("src/main/resources/default.json"); File modifiedFile = new File("src/main/resources/modifiedDefault.json"); // 可选:用Patch文件合并的方式 // File patchFile = new File("src/main/resources/config-patch.json"); // return patchService.mergeDefaultWithPatch(defaultFile, patchFile); return patchService.mergeDefaultWithModified(defaultFile, modifiedFile); } }
关键注意事项
- 数组处理:默认JsonPatch会生成数组元素级操作(如add/remove/replace),若需完全替换数组,直接使用递归合并更简便;若需精确修改数组元素,优先用JsonPatch。
- 依赖版本:确保
jackson-module-jsonpatch版本与Spring Boot自带的Jackson版本一致,避免依赖冲突。 - 文件读取:实际项目中建议通过
ResourceLoader读取classpath下的资源文件,而非硬编码路径。
内容的提问来源于stack exchange,提问作者Harsh
相关产品推荐
相关产品推荐

