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

Jackson如何生成带互斥属性约束的JSON Schema

实现方案

优先方案:Jackson原生注解实现

你可以直接使用Jackson原生提供的@JsonSchemaInject注解,将需要的oneOf互斥约束直接注入到生成的JSON Schema根节点,不需要额外引入第三方依赖,生成结果和你给出的示例Schema校验效果完全一致。
改造后的POJO代码如下:

import com.fasterxml.jackson.annotation.JsonSchemaInject;

@JsonSchemaInject(
    strings = {
        "oneOf:[{\"required\":[\"a\"],\"not\":{\"required\":[\"b\"]}},{\"required\":[\"b\"],\"not\":{\"required\":[\"a\"]}}]"
    }
)
class MyClass {
    private int a;
    private int b;

    // 自行补充getter、setter、构造方法
}

生成Schema的示例代码:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;

public class SchemaGenTest {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        JsonSchemaGenerator schemaGenerator = new JsonSchemaGenerator(mapper);
        JsonNode schema = schemaGenerator.generateSchema(MyClass.class);
        // 输出的Schema会自动携带你定义的oneOf约束,符合draft-04规范
        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
    }
}

注意:该方案需要引入com.fasterxml.jackson.module:jackson-module-jsonSchema依赖,2.x及以上版本均支持该注解。

其他可选方案

  • 无侵入动态修改Schema
    如果你不想给POJO加耦合注解,可以在生成基础Schema之后,手动修改JsonNode插入oneOf约束,示例代码:
    import com.fasterxml.jackson.databind.node.ArrayNode;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    
    public class SchemaGenTest {
        public static void main(String[] args) throws Exception {
            ObjectMapper mapper = new ObjectMapper();
            JsonSchemaGenerator schemaGenerator = new JsonSchemaGenerator(mapper);
            ObjectNode schema = (ObjectNode) schemaGenerator.generateSchema(MyClass.class);
    
            // 构造oneOf约束节点
            ArrayNode oneOfArray = mapper.createArrayNode();
            // 分支1:必须传a,禁止传b
            ObjectNode branchA = mapper.createObjectNode();
            branchA.set("required", mapper.createArrayNode().add("a"));
            branchA.set("not", mapper.createObjectNode()
                    .set("required", mapper.createArrayNode().add("b")));
            // 分支2:必须传b,禁止传a
            ObjectNode branchB = mapper.createObjectNode();
            branchB.set("required", mapper.createArrayNode().add("b"));
            branchB.set("not", mapper.createObjectNode()
                    .set("required", mapper.createArrayNode().add("a")));
            oneOfArray.add(branchA).add(branchB);
    
            schema.set("oneOf", oneOfArray);
            // 最终得到符合要求的Schema
        }
    }
    
  • 校验层单独实现约束
    如果你不需要把互斥规则体现在生成的JSON Schema中,也可以在参数校验环节实现该逻辑:比如自定义Jakarta Validation类级别校验注解,或者在业务代码中手动判断a、b的传参情况,确保仅传入其中一个。

内容的提问来源于stack exchange,提问作者Moha the almighty camel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:15:42