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

Java中如何判断一个通用JSON是否为另一个通用JSON的子集?

Java中判断一个JSON是否包含于另一个JSON的可靠方案

问题分析

你需要判断子JSON的所有键值对完全匹配父JSON中的对应键值(忽略父JSON的其他属性),但从Excel读取JSON时现有方案时灵时不灵,核心原因大概率是Excel读取的JSON字符串存在格式瑕疵(比如隐形空格、中文引号、转义不规范),或者原方案的递归逻辑未覆盖边界场景。

解决思路

  1. 先标准化Excel读取的JSON字符串:确保解析前格式合法,避免因格式问题导致解析失败或匹配错误。
  2. 基于成熟JSON库实现递归匹配:用Jackson/Gson这类工业级库处理JSON解析与遍历,比手写递归更稳定。

具体实现(以Jackson为例)

步骤1:依赖引入(Maven)

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version> <!-- 使用最新稳定版 -->
</dependency>

步骤2:JSON字符串预处理工具

处理Excel读取的字符串,修复常见格式问题:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonPreprocessor {
    public static String normalizeJson(String rawJson) {
        if (rawJson == null) return null;
        // 替换中文引号为英文引号
        rawJson = rawJson.replaceAll("“|”", "\"");
        // 去除键值对前后的多余空格(比如" name ": " Michael " → "name": "Michael")
        rawJson = rawJson.replaceAll("\\s*([{}\\[\\],:])\\s*", "$1");
        // 去除字符串值前后的多余空格(保留内部空格,比如" Michael Jordan " → "Michael Jordan")
        Pattern pattern = Pattern.compile("\"(.*?)\"");
        Matcher matcher = pattern.matcher(rawJson);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "\"" + matcher.group(1).trim() + "\"");
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
}

步骤3:递归判断JSON包含关系

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

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

    // 判断子JSON是否包含于父JSON
    public static boolean isJsonContained(String childJsonStr, String parentJsonStr) throws IOException {
        // 先标准化JSON字符串
        String normalizedChild = JsonPreprocessor.normalizeJson(childJsonStr);
        String normalizedParent = JsonPreprocessor.normalizeJson(parentJsonStr);

        JsonNode childNode = OBJECT_MAPPER.readTree(normalizedChild);
        JsonNode parentNode = OBJECT_MAPPER.readTree(normalizedParent);

        return isNodeContained(childNode, parentNode);
    }

    // 递归检查单个JsonNode的包含关系
    private static boolean isNodeContained(JsonNode childNode, JsonNode parentNode) {
        // 如果子节点是对象类型
        if (childNode.isObject() && parentNode.isObject()) {
            // 遍历子对象的所有键
            for (String key : childNode.fieldNames()) {
                if (!parentNode.has(key)) {
                    // 父JSON没有该键,直接返回false
                    return false;
                }
                JsonNode childValue = childNode.get(key);
                JsonNode parentValue = parentNode.get(key);
                // 递归检查子值是否匹配
                if (!isNodeContained(childValue, parentValue)) {
                    return false;
                }
            }
            return true;
        }
        // 如果子节点是数组类型:默认要求子数组的每个元素按顺序匹配父数组对应位置(可按需调整为子集匹配)
        else if (childNode.isArray() && parentNode.isArray()) {
            if (childNode.size() > parentNode.size()) {
                return false;
            }
            for (int i = 0; i < childNode.size(); i++) {
                if (!isNodeContained(childNode.get(i), parentNode.get(i))) {
                    return false;
                }
            }
            return true;
        }
        // 其他类型(字符串、数字、布尔、null)直接比较值
        else {
            return childNode.equals(parentNode);
        }
    }

    // 测试示例
    public static void main(String[] args) throws IOException {
        String parentJson = "{\"id\": \"1\",\"name\": \"Michael Jordan\",\"age\": \"50\"}";
        String childJson = "{\"name\": \"Michael Jordan\"}";
        // 模拟Excel读取的带格式问题的JSON
        String messyChildJson = "{ “name” : \" Michael Jordan \" }";

        System.out.println(isJsonContained(childJson, parentJson)); // 输出true
        System.out.println(isJsonContained(messyChildJson, parentJson)); // 输出true(预处理后修复了格式)
    }
}

关键说明

  • 预处理的重要性:Excel单元格中的JSON常存在格式问题(比如用户输入时的空格、中文引号),预处理步骤能大幅降低解析失败概率,这是解决"时灵时不灵"的核心。
  • 递归逻辑覆盖场景:不仅支持简单键值对,还支持嵌套JSON和数组的匹配(数组匹配逻辑可根据需求调整,比如改为父数组包含子数组的所有元素,而不要求顺序)。
  • 成熟库的优势:Jackson的JsonNode提供了完善的类型判断和值比较方法,比手写递归更稳定,能避免空指针、类型转换等隐藏问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 22:12:29