1. 简介
本文将介绍 Manifold JSON——一个基于 JSON Schema 的 JSON 文档解析工具。我们将探讨它的功能、应用场景以及使用方法。
Manifold 是一套编译器插件集合,为 Java 应用提供多种高效特性。本文重点讲解如何利用它根据 JSON Schema 文件解析和构建 JSON 文档。
2. 安装
使用 Manifold 前必须确保编译器已正确配置。核心集成是作为 Java 编译器插件,需在 Maven 或 Gradle 项目中配置。此外,Manifold 还提供 IDE 插件提升开发体验。
2.1. Maven 编译器插件
在 Maven 中集成 Manifold 需同时添加依赖和编译器插件,两者版本必须一致(当前最新版为 2024.1.20)。
添加依赖与普通 Maven 依赖无异:
<dependency>
<groupId>systems.manifold</groupId>
<artifactId>manifold-json-rt</artifactId>
<version>2024.1.20</version>
</dependency>
编译器插件配置需修改 maven-compiler-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<compilerArgs>
<!-- 配置 manifold 插件 -->
<arg>-Xplugin:Manifold</arg>
</compilerArgs>
<!-- 添加注解处理器路径 -->
<annotationProcessorPaths>
<path>
<groupId>systems.manifold</groupId>
<artifactId>manifold-json</artifactId>
<version>2024.1.20</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
这里做了两件事:
- 添加
-Xplugin:Manifold
编译参数 - 配置 Manifold JSON 注解处理器(负责从 Schema 生成代码)
2.2. Gradle 编译器插件
Gradle 集成方式类似但配置更简洁:
dependencies {
implementation 'systems.manifold:manifold-json-rt:2024.1.20'
annotationProcessor 'systems.manifold:manifold-json:2024.1.20'
testAnnotationProcessor 'systems.manifold:manifold-json:2024.1.20'
}
仍需手动添加编译参数:
tasks.withType(JavaCompile) {
options.compilerArgs += ['-Xplugin:Manifold']
}
至此环境准备就绪。
2.3. IDE 插件
除构建工具插件外,Manifold 还提供 IntelliJ/Android Studio 插件:
安装后,IDE 内编译即可触发 Manifold 插件,无需依赖构建工具。
3. 使用 JSON Schema 定义类
配置完成后,在 src/main/resources
(或 src/test/resources
)目录创建 JSON Schema 文件即可定义类。文件路径将直接映射为完整类名。
例如创建 com.baeldung.manifold.SimpleUser
类:
路径:src/main/resources/com/baeldung/manifold/SimpleUser.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "http://baeldung.com/manifold/SimpleUser.json",
"type": "object",
"properties": {
"username": {
"type": "string",
"maxLength": 100
},
"name": {
"type": "string",
"maxLength": 80
},
"email": {
"type": "string",
"format": "email",
"maxLength": 260
}
},
"required": [
"username",
"name"
]
}
这定义了一个包含三个 String
字段的类:username
、name
和 email
。
⚠️ 重要:Manifold 采用惰性生成机制,仅当代码引用 Schema 文件时才会生成类。哪怕简单变量定义也算有效引用。
4. 实例化 Manifold 类
生成的类并非标准 Java 类,而是接口。因此不能直接使用 new
创建实例。
生成代码提供了静态 create()
方法作为构造器,需按 required
数组顺序传入必填字段:
public static SimpleUser create(String username, String name);
其他字段可通过 setter 填充:
SimpleUser user = SimpleUser.create("testuser", "Test User");
user.setEmail("[email protected]");
还支持 Builder 模式,通过 build()
方法链式调用:
SimpleUser user = SimpleUser.builder("testuser", "Test User")
.withEmail("[email protected]")
.build();
✅ 对于只读可选字段,Builder 模式是唯一赋值途径——实例创建后无法修改此类字段。
5. 解析 JSON
生成类提供 load()
方法从多种数据源解析 JSON:
解析方式
fromJson()
:解析 JSON 字符串fromJsonFile()
:从文件读取fromJsonReader()
:从 Reader 读取fromJsonUrl()
:从 URL 读取(底层使用java.net.URL.openStream()
)
字符串解析示例
SimpleUser user = SimpleUser.load().fromJson("""
{
"username": "testuser",
"name": "Test User",
"email": "[email protected]"
}
""");
文件流解析示例
InputStream is = getClass().getResourceAsStream("/com/baeldung/manifold/simpleUserData.json");
InputStreamReader reader = new InputStreamReader(is);
SimpleUser user = SimpleUser.load().fromJsonReader(reader);
❌ 解析失败会抛出 RuntimeException
,内嵌 manifold.rt.api.ScriptException
描述具体错误。
6. 生成 JSON
与解析对应,生成类提供 write()
方法将对象转为 JSON:
生成方式
toJson()
:返回 JSON 字符串- 写入任何
Appendable
实现(如Writer
、StringBuilder
)
字符串生成示例
SimpleUser user = SimpleUser.builder("testuser", "Test User")
.withEmail("[email protected]")
.build();
String json = user.write().toJson();
文件写入示例
user.write().toJson(writer); // writer 可指向文件/网络等
✅ 支持写入内存缓冲区、文件或网络连接等任意目标。
7. 其他格式支持
虽然核心是 JSON,但 Manifold 也支持 CSV、XML 和 YAML:
需添加对应依赖:
- CSV:
systems.manifold:manifold-csv-rt
- XML:
systems.manifold:manifold-xml-rt
- YAML:
systems.manifold:manifold-yaml-rt
多格式示例
SimpleUser user = SimpleUser.load().fromXmlReader(reader);
String yaml = user.write().toYaml();
8. JSON Schema 高级特性
8.1. 只读/只写字段
只读字段(readOnly: true
)不生成 setter:
"username": {
"type": "string",
"readOnly": true
},
只能在构造或解析时赋值,后续不可修改。
只写字段(writeOnly: true
)不生成 getter:
"mfaCode": {
"type": "string",
"writeOnly": true
},
可赋值但无法通过 Java 类读取(生成 JSON 时仍会输出)。
8.2. 格式化类型
Schema 中的 format
会影响生成的 Java 类型:
date-time
→java.time.LocalDateTime
email
→String
(带格式校验)
8.3. 动态属性
additionalProperties: true
允许任意扩展字段(默认开启):
user.put("note", "Schema 未定义的字段");
⚠️ 警告:无类型校验,可能覆盖 Schema 定义字段。
patternProperties
部分支持:
"patternProperties": {
"note[0-9]": {
"type": "string"
}
}
Manifold 会将其视为 additionalProperties: true
。
8.4. 嵌套类型
支持在 Schema 中定义嵌套对象:
{
"properties": {
"email": {
"type": "object",
"properties": {
"address": { "type": "string" },
"verified": { "type": "boolean" }
},
"required": ["address", "verified"]
}
}
}
生成内部类,使用方式:
User user = User.builder()
.withEmail(User.email.builder("[email protected]", false).build())
.build();
8.5. 类型组合
支持 allOf
/anyOf
/oneOf
组合类型:
allOf 示例(合并所有属性)
"allOf": [
{"properties": {"username": {"type": "string"}}},
{"properties": {"roles": {"type": "array", "items": {"type": "string"}}}}
]
生成类包含所有字段:
Composed.user.builder()
.withUsername("testuser")
.withRoles(List.of("admin"))
.build()
anyOf/oneOf 示例(类型安全多选)
"anyOf": [
{"$ref": "#/definitions/Dog"},
{"$ref": "#/definitions/Cat"}
]
生成类型安全方法:
Composed composed = Composed.builder()
.withAnimalAsCat(Composed.Cat.builder()
.withColor("ginger")
.build())
.build();
assertEquals("ginger", composed.getAnimalAsCat().getColor());
9. 总结
本文全面介绍了 Manifold JSON 的核心功能。这个库还有更多高级特性等你探索,不妨亲自上手试试?