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

如何找到可解析JSON Schema内部$ref引用的Java工具库?

解决方案

方案1:使用现成第三方库

你可以使用com.networknt:json-schema-validator库,这是Java生态中JSON Schema相关功能支持最完善的开源库之一,原生支持内部$ref的内联展开,无需处理外部引用的情况下配置成本极低。
Maven依赖示例:

<dependency>
    <groupId>com.networknt</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>1.0.87</version>
</dependency>

核心使用逻辑如下:

  1. 读取原始JSON Schema字符串为JsonNode对象
  2. 配置SchemaFactory关闭外部引用解析
  3. 调用内置的dereference方法完成内联引用替换
  4. 输出处理后的Schema字符串即可得到你需要的结果

方案2:自定义轻量实现(可保留现有everit依赖)

如果你不想替换现有依赖,且仅需要处理内部#/$defs格式的引用,完全可以自己实现简单的递归替换逻辑,100行以内代码即可完成需求,示例代码基于Jackson实现:

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

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

    public static String inlineRefs(String rawSchema) throws Exception {
        ObjectNode rootNode = (ObjectNode) OBJECT_MAPPER.readTree(rawSchema);
        // 提前提取所有内部定义
        ObjectNode defsNode = (ObjectNode) rootNode.get("$defs");
        // 递归遍历替换所有内部引用
        recursiveReplace(rootNode, defsNode);
        // 删除已无用的defs节点
        rootNode.remove("$defs");
        return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
    }

    private static void recursiveReplace(JsonNode currentNode, ObjectNode defsNode) {
        if (currentNode.isObject()) {
            ObjectNode currentObj = (ObjectNode) currentNode;
            // 判断当前节点是否是引用节点
            if (currentObj.has("$ref")) {
                String refPath = currentObj.get("$ref").asText();
                // 仅处理内部defs引用
                if (refPath.startsWith("#/$defs/")) {
                    String defKey = refPath.substring("#/$defs/".length());
                    JsonNode targetDef = defsNode.get(defKey);
                    // 替换当前节点内容
                    currentObj.removeAll();
                    currentObj.setAll((ObjectNode) targetDef);
                }
            }
            // 递归遍历所有子字段
            currentObj.fields().forEachRemaining(entry -> recursiveReplace(entry.getValue(), defsNode));
        } else if (currentNode.isArray()) {
            // 递归遍历数组中所有元素
            currentNode.forEach(item -> recursiveReplace(item, defsNode));
        }
    }
}

提示:如果你的Schema存在循环引用的情况,可以额外增加一个已处理路径的Set做校验,避免递归栈溢出,无循环引用的场景以上代码可直接使用,完全符合你给出的示例需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 21:45:03