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

能否通过编程方式展开JSON Schema中的引用以实现载荷校验与字段过滤?

方案1:基于现有json-schema-validator库实现Schema引用展开

你当前使用的json-schema-validator库本身已经完成了所有$ref的解析逻辑,只需要自己补一层递归展开的代码即可:

  • 首先通过SchemaLoader加载原始Schema得到JsonSchema实例,它内部已经通过RefResolver完成了所有引用的寻址,不需要自己处理引用路径解析
  • 递归遍历Schema节点,遇到$ref字段时直接调用getRefSchema()方法获取引用对应的实际Schema节点,替换当前的$ref节点即可
  • 新增已处理引用路径的Set做校验,避免循环引用导致的死循环问题

参考代码示例:

// 加载原始Schema
JsonNode rawSchema = objectMapper.readTree(originSchemaStr);
SchemaLoader loader = SchemaLoader.builder().schemaJson(rawSchema).build();
JsonSchema jsonSchema = loader.load().build();

// 递归展开引用的方法
private JsonNode resolveSchemaRefs(JsonNode node, JsonSchema schema, Set<String> processedRefs) throws URISyntaxException {
    if (node.isObject()) {
        ObjectNode objNode = (ObjectNode) node;
        // 遇到$ref则替换为实际Schema节点
        if (objNode.has("$ref")) {
            String refVal = objNode.get("$ref").asText();
            if (processedRefs.contains(refVal)) {
                return objNode; // 循环引用直接返回,避免死循环
            }
            processedRefs.add(refVal);
            JsonNode refSchemaNode = schema.getRefSchema(new JsonRef(new URI(refVal))).getSchemaNode();
            return resolveSchemaRefs(refSchemaNode, schema, processedRefs);
        }
        // 遍历所有子字段递归处理
        Iterator<Map.Entry<String, JsonNode>> fieldIter = objNode.fields();
        while (fieldIter.hasNext()) {
            Map.Entry<String, JsonNode> entry = fieldIter.next();
            objNode.set(entry.getKey(), resolveSchemaRefs(entry.getValue(), schema, processedRefs));
        }
    } else if (node.isArray()) {
        ArrayNode arrayNode = (ArrayNode) node;
        for (int i = 0; i < arrayNode.size(); i++) {
            arrayNode.set(i, resolveSchemaRefs(arrayNode.get(i), schema, processedRefs));
        }
    }
    return node;
}

处理后得到的无引用Schema就可以直接传给你当前使用的过滤库。

方案2:换用一站式校验+过滤库

如果不想自己维护引用展开逻辑,可以直接换用同时支持校验、引用解析、自动过滤未定义字段的库,比两个库拼接的方案更稳定:
可以使用networknt的json-schema-validator库,它内置了完整的$ref解析能力,只需要开启removeAdditionalProperties配置,校验的同时会自动删除所有Schema未定义的字段,完全满足你的业务需求。

参考代码示例:

SchemaValidatorsConfig config = new SchemaValidatorsConfig();
config.setRemoveAdditionalProperties(true); // 开启自动过滤未定义字段
// 指定Schema版本,按你的实际使用场景选择
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7);
JsonSchema schema = factory.getSchema(originSchemaStr, config);
// 校验的同时完成字段过滤
Set<ValidationMessage> validateErrors = schema.validate(payloadNode);
// 校验完成后payloadNode已经移除了所有Schema未定义的字段

额外建议

如果是PII字段过滤场景,建议额外维护一份敏感字段黑名单做二次校验,避免Schema编写遗漏导致敏感数据落库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:48:03