1. 概述
本教程将使用 Java JSON Schema Generator 库,在 Java 中创建 JSON Schema。我们将学习:
✅ 生成简单和递归的 JSON Schema
✅ 配置不同的 Schema 参数
✅ 使用 Jackson 和 Jakarta Validation 模块派生 Schema
✅ 通过 Maven 插件 在构建时生成 Schema
2. 环境准备
2.1 核心依赖
首先添加核心依赖 *jsonschema-generator*:
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-generator</artifactId>
<version>4.31.1</version>
</dependency>
该依赖包含 Schema 生成和配置的主要 API
2.2 扩展模块
接下来安装三个模块,用于从类注解生成 Schema 属性:
Jackson 模块
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-module-jackson</artifactId>
<version>4.31.1</version>
</dependency>
Jakarta Validation 模块
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-module-jakarta-validation</artifactId>
<version>4.31.1</version>
</dependency>
2.3 Maven 插件
最后添加构建插件:
<plugin>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-maven-plugin</artifactId>
<version>4.31.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
⚠️ 重要提示:自 4.7 版本起,强烈建议模块和插件使用与核心依赖相同的版本。
3. 基础用法
3.1 简单 Schema
定义一个 Article
类:
public class Article {
private UUID id;
private String title;
private String content;
private Date createdAt;
private Area area;
// getters and setters omitted
}
生成 Schema:
SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON);
SchemaGeneratorConfig config = configBuilder.with(Option.EXTRA_OPEN_API_FORMAT_VALUES)
.without(Option.FLATTENED_ENUMS_FROM_TOSTRING)
.build();
SchemaGenerator generator = new SchemaGenerator(config);
JsonNode jsonSchema = generator.generateSchema(Article.class);
关键配置说明:
DRAFT_2020_12
:使用最新 JSON Schema 规范(默认为DRAFT-7
)PLAIN_JSON
预设:仅使用非静态类字段生成 SchemaEXTRA_OPEN_API_FORMAT_VALUES
:为特殊类型添加格式信息(如 UUID/date-time)
生成的 Schema:
{
"$schema":"https://json-schema.org/draft/2020-12/schema",
"type":"object",
"properties":{
"area":{
"type":"string",
"enum":["JAVA","KOTLIN","SCALA","LINUX"]
},
"content":{"type":"string"},
"createdAt":{
"type":"string",
"format":"date-time"
},
"id":{
"type":"string",
"format":"uuid"
},
"title":{"type":"string"}
}
}
📌 Java 的
Date
和UUID
被转换为带format
的字符串类型,枚举通过name()
方法转换
3.2 递归 Schema
定义递归类结构:
public class Author {
private UUID id;
private String name;
private String role;
private List<AuthoredArticle> articles;
// getters, setters omitted
}
public class AuthoredArticle {
private Author author;
// getters and setters omitted
}
生成的 Schema 会包含循环引用:
{
"author":{
"type":"object",
"properties":{
"articles":{
"type":"array",
"items":{"$ref":"#"}
}
}
}
}
✅ 规范允许循环引用,但
$ref
不能指向另一个$ref
4. 高级配置
4.1 字段级配置
自定义 Author
类的 Schema 字段:
configBuilder.forFields()
.withRequiredCheck(field -> field.getAnnotationConsideringFieldAndGetter(Nullable.class) == null)
.withArrayUniqueItemsResolver(scope -> scope.getType().getErasedType() == List.class ? true : null);
效果:
- 非
@Nullable
字段标记为required
List
类型字段添加uniqueItems: true
生成的 Schema:
{
"type":"object",
"properties":{
"articles":{
"uniqueItems":true,
"type":"array",
"items":{
"type":"object",
"properties":{...},
"required":["area","author","content","createdAt","id","title"]
},
"default":[]
}
},
"required":["articles","id","name","role"]
}
类型级默认值配置:
configBuilder.forTypesInGeneral()
.withDefaultResolver(scope ->
scope.getType().getErasedType() == List.class ? Collections.EMPTY_LIST : null)
.withDefaultResolver(scope ->
scope.getType().getErasedType() == Date.class ? Date.from(Instant.now()) : null);
📌 返回
null
表示不在 Schema 中设置该属性
4.2 高级配置
使用 AdvancedArticle
类演示:
public class AdvancedArticle {
private UUID id;
private String title;
@AllowedTypes({Timestamp.class, String.class, Date.class})
private Object createdAt;
// other fields omitted
}
添加只读属性:
configBuilder.forFields()
.withInstanceAttributeOverride((node, field, context) ->
node.put("readOnly", field.getDeclaredType().isInstanceOf(UUID.class)));
效果:
{
"id":{
"type":"string",
"format":"uuid",
"readOnly":true
},
"title":{
"type":"string",
"readOnly":false
}
}
处理多类型字段:
configBuilder.forFields()
.withTargetTypeOverridesResolver(field ->
Optional.ofNullable(field.getAnnotationConsideringFieldAndGetterIfSupported(AllowedTypes.class))
.map(AllowedTypes::value)
.map(Stream::of)
.map(stream -> stream.map(subtype -> field.getContext().resolve(subtype)))
.map(stream -> stream.collect(Collectors.toList()))
.orElse(null));
生成的联合类型:
{
"createdAt":{
"anyOf":[
{"type":"object","properties":{"nanos":{"type":"integer","format":"int32"}}},
{"type":"string","format":"date-time"}
]
}
}
💡 高级配置支持自定义类型定义和属性定义,满足复杂场景需求
5. 模块使用
5.1 Jackson 模块
处理 Person
类的 Jackson 注解:
class Person {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
UUID id;
@JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true)
String name;
@JsonIgnore
String fullName;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Date createdAt;
// other fields omitted
}
配置模块:
JacksonModule module = new JacksonModule(RESPECT_JSONPROPERTY_REQUIRED);
SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(DRAFT_2020_12, PLAIN_JSON)
.with(module)
.with(EXTRA_OPEN_API_FORMAT_VALUES);
生成的 Schema:
{
"type":"object",
"properties":{
"createdAt":{
"type":"string",
"format":"date-time",
"readOnly":true
},
"id":{
"type":"string",
"format":"uuid",
"readOnly":true
}
},
"required":["address","name","surname"]
}
✅ 自动忽略
@JsonIgnore
字段,正确处理required
和readOnly
5.2 Jakarta Validation 模块
使用验证注解装饰 Person
类:
class Person {
@NotNull UUID id;
@NotNull @Email
@Pattern(regexp = "\\b[A-Za-z0-9._%+-]+@baeldung\\.com\\b")
String email;
@Null String fullName;
@Size(max = 10)
List<Person> friends;
// other fields omitted
}
配置模块:
JakartaValidationModule module = new JakartaValidationModule(
NOT_NULLABLE_FIELD_IS_REQUIRED,
INCLUDE_PATTERN_EXPRESSIONS
);
生成的 Schema:
{
"type":"object",
"properties":{
"email":{
"type":"string",
"format":"email",
"pattern":"\\b[A-Za-z0-9._%+-]+@baeldung\\.com\\b"
},
"friends":{
"maxItems":10,
"type":"array",
"items":{"$ref":"#"}
},
"fullName":{
"type":["string","null"]
}
},
"required":["createdAt","email","id","name","surname"]
}
📌
format
字段,@Size
转换为maxItems
6. Maven 插件配置
完整插件配置示例:
<plugin>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-maven-plugin</artifactId>
<version>4.31.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<packageNames>
<packageName>com.baeldung.jsonschemageneration.plugin</packageName>
</packageNames>
<classNames>
<className>com.baeldung.jsonschemageneration.plugin.Person</className>
</classNames>
<schemaVersion>DRAFT_2020_12</schemaVersion>
<schemaFilePath>src/main/resources/schemas</schemaFilePath>
<schemaFileName>{1}/{0}.json</schemaFileName>
<failIfNoClassesMatch>true</failIfNoClassesMatch>
<options>
<preset>PLAIN_JSON</preset>
<enabled>
<option>DEFINITIONS_FOR_ALL_OBJECTS</option>
<option>FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT</option>
</enabled>
<disabled>SCHEMA_VERSION_INDICATOR</disabled>
</options>
<modules>
<module>
<name>Jackson</name>
<options>
<option>RESPECT_JSONPROPERTY_REQUIRED</option>
</options>
</module>
<module>
<name>JakartaValidation</name>
<options>
<option>NOT_NULLABLE_FIELD_IS_REQUIRED</option>
<option>INCLUDE_PATTERN_EXPRESSIONS</option>
</options>
</module>
</modules>
</configuration>
</plugin>
执行 mvn compile
后生成文件路径:
src/main/resources/schemas/com/baeldung/jsonschemageneration/plugin/Person.json
⚠️ 插件不支持自定义模块的选项配置
7. 总结
本文系统介绍了使用 Java JSON Schema Generator 的核心能力:
- 基础生成:支持简单/递归 Schema,自动处理 Java 类型转换
- 灵活配置:字段级、类型级、方法级精细控制
- 模块化扩展:Jackson/Jakarta Validation 注解自动转换
- 构建集成:通过 Maven 插件实现自动化生成
完整代码示例可在 GitHub 获取