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

Java中如何局部更新JSONObject且不丢失原有字段?

如何深度更新JSONObject而不丢失原有字段

要实现仅用部分JSON更新原JSONObject且保留未涉及字段,核心是递归遍历并合并层级结构:遇到嵌套对象时递归合并,遇到数组、基本类型(字符串/数字/布尔)则直接替换。以下是两种主流语言的通用实现:

Python 实现

用字典模拟JSONObject,写一个递归深度更新函数:

def deep_update(original, update):
    for key, value in update.items():
        # 如果当前更新值是字典,且原对象对应key也是字典,递归合并
        if isinstance(value, dict) and key in original and isinstance(original[key], dict):
            deep_update(original[key], value)
        # 否则直接替换(数组、基本类型或原对象无此key的情况)
        else:
            original[key] = value
    return original

测试示例

# 原JSON转字典
original_json = {
    "title": "Lamp",
    "events": {
        "overheating": {
            "data": {"type": "string"},
            "forms": [{"href": "https://www.lamp.com/oh", "subprotocol": "longpoll"}]
        }
    },
    "actions": {"toggle": {"forms": [{"href": "https://lampione.it/toggle"}]}},
    "@context": "https://www.w3.org/2019/wot/td/v1",
    "security": ["basic_sc"],
    "properties": {},
    "securityDefinitions": {"basic_sc": {"in": "header", "scheme": "basic"}},
    "id": "urn:uuid:8c426e18-f579-42b1-a3c9-7aa9c86fbacf"
}

# 更新部分转字典
update_json = {
    "events": {
        "overheating": {
            "forms": [{"href": "https://lampada.it/oh", "subprotocol": "longpoll"}]
        }
    }
}

# 执行更新
updated_json = deep_update(original_json, update_json)

# 验证结果:events.overheating.data 被保留,forms 已更新
print(updated_json["events"]["overheating"]["data"])  # 输出: {'type': 'string'}
print(updated_json["events"]["overheating"]["forms"][0]["href"])  # 输出: https://lampada.it/oh

Java 实现(基于Jackson)

利用Jackson的JsonNode和ObjectNode实现递归深度合并:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class JsonDeepUpdater {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static JsonNode deepUpdate(JsonNode originalNode, JsonNode updateNode) {
        // 仅处理对象类型的节点合并
        if (originalNode.isObject() && updateNode.isObject()) {
            ObjectNode originalObj = (ObjectNode) originalNode;
            // 遍历更新节点的所有字段
            updateNode.fields().forEachRemaining(entry -> {
                String key = entry.getKey();
                JsonNode updateValue = entry.getValue();
                // 若原节点有该key且都是对象,递归合并
                if (originalObj.has(key) && originalObj.get(key).isObject() && updateValue.isObject()) {
                    originalObj.set(key, deepUpdate(originalObj.get(key), updateValue));
                } else {
                    // 否则直接替换(数组、基本类型或新增字段)
                    originalObj.set(key, updateValue);
                }
            });
            return originalObj;
        }
        // 非对象类型直接返回更新值
        return updateNode;
    }

    // 测试用例
    public static void main(String[] args) throws Exception {
        String originalStr = "{\"title\":\"Lamp\",\"events\":{\"overheating\":{\"data\":{\"type\":\"string\"},\"forms\":[{\"href\":\"https://www.lamp.com/oh\",\"subprotocol\":\"longpoll\"}]}},\"actions\":{\"toggle\":{\"forms\":[{\"href\":\"https://lampione.it/toggle\"}]}},\"@context\":\"https://www.w3.org/2019/wot/td/v1\",\"security\":[\"basic_sc\"],\"properties\":{},\"securityDefinitions\":{\"basic_sc\":{\"in\":\"header\",\"scheme\":\"basic\"}},\"id\":\"urn:uuid:8c426e18-f579-42b1-a3c9-7aa9c86fbacf\"}";
        String updateStr = "{\"events\":{\"overheating\":{\"forms\":[{\"href\":\"https://lampada.it/oh\",\"subprotocol\":\"longpoll\"}]}}}";

        JsonNode original = OBJECT_MAPPER.readTree(originalStr);
        JsonNode update = OBJECT_MAPPER.readTree(updateStr);

        JsonNode updated = deepUpdate(original, update);

        // 验证结果
        System.out.println(updated.get("events").get("overheating").get("data")); // 输出: {"type":"string"}
        System.out.println(updated.get("events").get("overheating").get("forms").get(0).get("href")); // 输出: "https://lampada.it/oh"
    }
}

注意事项

  • 数组处理:上述实现中数组会被直接替换,如果需要追加数组元素而非替换,需修改逻辑判断数组类型并做合并操作。
  • 空值处理:若更新JSON中包含null值,会直接覆盖原字段的非空值,若需跳过null更新,可在函数中增加判断逻辑。
  • 新增字段:更新JSON中的新增字段会直接添加到原JSONObject中。

内容的提问来源于stack exchange,提问作者simonetassi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:55:00