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

Java REST API中JSON Schema校验及自定义函数调用技术咨询

我来帮你把这些问题理清楚,都是Java REST API里做JSON Schema校验时的常见需求,一个个说:

一、JSON Schema调用自定义函数遵循的规则

标准的JSON Schema(比如Draft 7/2019-09/2020-12这些官方版本)本身并没有内置“直接调用自定义函数”的语法——毕竟它是跨语言的通用规范,得保证不同语言的校验器都能兼容。但几乎所有Java的JSON Schema校验库都支持自定义关键字扩展:你可以定义一个专属的关键字(比如customPerilCheck),然后在校验库中给这个关键字绑定你的自定义校验逻辑(也就是你说的自定义函数),最终在Schema里通过这个关键字触发校验。

二、JSON Schema编写的标准

JSON Schema有官方的演进版本,目前主流且支持度最高的是:

  • Draft 7:兼容性最广,大部分库都完美支持
  • Draft 2019-09:新增了一些模块化、元数据相关的特性
  • Draft 2020-12:最新稳定版,优化了部分语法和功能

编写Schema时必须通过$schema字段声明遵循的版本,比如:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "http://example.com/example.json",
  "type": "object"
}

基础的类型约束、格式校验、枚举、必填项等都要遵循对应版本的官方规则,自定义逻辑只能通过扩展关键字实现,不能直接在Schema里写函数代码。

三、Jackson对JSON Schema的支持

Jackson提供了jackson-module-jsonSchema模块,但它的核心能力是从Java对象生成JSON Schema,原生并不支持“用Schema校验JSON数据”,也没有内置的自定义校验扩展。

如果想用Jackson做校验,通常需要结合专门的JSON Schema校验库,或者自己扩展Jackson的校验逻辑。更推荐直接用专门的校验库,比如:

  • com.networknt/json-schema-validator:轻量高性能,扩展自定义关键字很方便
  • org.everit.json.schema:老牌稳定库,支持丰富的扩展场景
四、针对peril属性的自定义函数校验示例

下面用com.networknt/json-schema-validator库做演示,它的扩展流程比较清晰:

1. 添加Maven依赖

<dependency>
    <groupId>com.networknt</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>1.0.80</version> <!-- 建议用最新稳定版 -->
</dependency>

2. 编写带自定义关键字的Schema

给peril字段添加自定义关键字customPerilValidator,用来触发你的自定义校验逻辑:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "http://example.com/example.json",
  "type": "object",
  "properties": {
    "peril": {
      "type": "string",
      "customPerilValidator": true // 这里的值可以是配置参数,比如允许的风险列表
    }
  },
  "required": ["peril"]
}

3. 实现自定义校验器(你的自定义函数逻辑)

import com.networknt.schema.JsonValidator;
import com.networknt.schema.ValidationMessage;
import java.util.Set;

public class CustomPerilValidator implements JsonValidator {
    // 自定义校验逻辑:比如校验peril是否属于允许的风险类型
    private static final Set<String> ALLOWED_PERILS = Set.of("fire", "flood", "earthquake");

    @Override
    public Set<ValidationMessage> validate(Object node, com.networknt.schema.JsonSchema parentSchema, String instanceLocation, com.networknt.schema.ExecutionContext executionContext) {
        String perilValue = node.toString();
        if (!ALLOWED_PERILS.contains(perilValue)) {
            return Set.of(ValidationMessage.builder()
                    .instanceLocation(instanceLocation)
                    .keyword("customPerilValidator")
                    .message("无效的风险类型:" + perilValue + ",允许的值为:" + String.join(", ", ALLOWED_PERILS))
                    .build());
        }
        return Set.of(); // 校验通过返回空集合
    }
}

4. 注册关键字并执行校验

import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SpecVersion;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.InputStream;
import java.util.Set;

public class SchemaValidationDemo {
    public static void main(String[] args) throws Exception {
        // 加载Schema文件
        ObjectMapper mapper = new ObjectMapper();
        InputStream schemaStream = SchemaValidationDemo.class.getResourceAsStream("/example-schema.json");
        JsonNode schemaNode = mapper.readTree(schemaStream);

        // 创建Schema工厂并注册自定义关键字
        JsonSchemaFactory factory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012))
                .addKeyword(new com.networknt.schema.Keyword("customPerilValidator") {
                    @Override
                    public JsonValidator newValidator(String keyword, JsonNode schemaNode, com.networknt.schema.JsonSchema parentSchema, com.networknt.schema.ValidationContext validationContext) {
                        return new CustomPerilValidator();
                    }
                })
                .build();

        // 编译Schema并校验输入JSON
        JsonSchema schema = factory.getSchema(schemaNode);
        String inputJson = "{\"peril\": \"fire\"}"; // 合法输入
        // String inputJson = "{\"peril\": \"hurricane\"}"; // 非法输入,会触发校验错误
        JsonNode inputNode = mapper.readTree(inputJson);
        Set<ValidationMessage> errors = schema.validate(inputNode);

        // 输出校验结果
        if (errors.isEmpty()) {
            System.out.println("JSON校验通过!");
        } else {
            errors.forEach(error -> System.out.println("校验错误:" + error.getMessage()));
        }
    }
}
五、额外注意
  • 不同校验库的扩展方式略有差异,比如org.everit.json.schema是通过SchemaValidatorBuilder注册自定义关键字
  • 自定义关键字名称要避免和JSON Schema标准关键字冲突
  • 如果需要给自定义函数传递参数,可以把customPerilValidator的值设为对象(比如{"allowedValues": ["fire", "flood"]}),然后在校验器里读取这个参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:33:49