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
相关产品推荐
相关产品推荐

