如何在Gradle构建阶段运行Java代码生成JSON Schema
在Gradle构建阶段运行Java代码生成JSON Schema的方案
我完全理解你的困扰——用测试类来做构建阶段的代码生成确实有点“滥用”测试框架,而用run任务又会导致每次启动应用都无意义执行这段逻辑。下面是两种靠谱的方案,帮你把JSON Schema生成逻辑优雅地整合到Gradle构建流程里:
方案一:自定义JavaExec任务(推荐)
这个方案最直接,把你的生成代码改成可执行主类,然后在Gradle里创建一个专门的任务来运行它,既能灵活控制执行时机,又完全符合构建阶段的职责。
步骤1:修改Java代码为可执行主类
把原来的测试类改成带main方法的普通类,去掉JUnit相关注解,同时做一些小优化:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.victools.jsonschema.generator.Option; import com.github.victools.jsonschema.generator.OptionPreset; import com.github.victools.jsonschema.generator.SchemaGenerator; import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; import com.mypackage.MyClass; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Map; @SuppressWarnings({"FieldCanBeLocal", "rawtypes"}) public class JsonSchemaGenerator { private final String SCHEMA_FOLDER = "schemas/"; private final Map<Class, String> schemaToGenerate = Map.of( MyClass.class, "my-class.schema" ); public static void main(String[] args) throws Exception { new JsonSchemaGenerator().generateJsonSchema(); } private void generateJsonSchema() throws Exception { // 先创建输出目录,避免因文件夹不存在报错 Files.createDirectories(Paths.get(SCHEMA_FOLDER)); SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(new ObjectMapper(), OptionPreset.PLAIN_JSON); SchemaGeneratorConfig config = configBuilder.with(Option.DEFINITIONS_FOR_ALL_OBJECTS).build(); SchemaGenerator generator = new SchemaGenerator(config); for (var entry : schemaToGenerate.entrySet()) { JsonNode jsonSchema = generator.generateSchema(entry.getKey()); // 用try-with-resources自动关闭流,避免资源泄漏 try (PrintWriter out = new PrintWriter(SCHEMA_FOLDER + entry.getValue())) { out.println(jsonSchema.toPrettyString()); } } } }
步骤2:在build.gradle中配置自定义任务
在你的build.gradle(Groovy语法示例)里添加一个JavaExec类型的任务:
// 定义生成JSON Schema的自定义任务 task generateJsonSchema(type: JavaExec) { // 依赖compileJava任务,确保生成代码已经编译完成 dependsOn compileJava // 指定任务使用项目主源码的运行时类路径 classpath = sourceSets.main.runtimeClasspath // 替换成你的JsonSchemaGenerator类的全限定名 mainClass = 'com.mypackage.JsonSchemaGenerator' } // 可选:把任务绑定到构建生命周期,比如processResources之后自动执行 // 这样每次执行build时都会自动生成Schema,无需手动触发 processResources.finalizedBy generateJsonSchema
使用方式
- 手动执行:终端运行
./gradlew generateJsonSchema - 自动执行:如果配置了
finalizedBy,每次运行./gradlew build时,该任务会在processResources完成后自动执行,完全不会影响run任务的逻辑
方案二:直接在Gradle脚本中编写生成逻辑(进阶)
如果你不想维护单独的Java类,也可以把生成逻辑直接写到Gradle脚本里,用Groovy调用jsonschema-generator的API:
buildscript { dependencies { // 替换成你实际使用的依赖版本 classpath 'com.github.victools:jsonschema-generator:4.28.0' classpath 'com.fasterxml.jackson.core:jackson-databind:2.15.2' } } task generateJsonSchema { dependsOn compileJava doLast { def objectMapper = new com.fasterxml.jackson.databind.ObjectMapper() def configBuilder = new com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder(objectMapper, com.github.victools.jsonschema.generator.OptionPreset.PLAIN_JSON) configBuilder.with(com.github.victools.jsonschema.generator.Option.DEFINITIONS_FOR_ALL_OBJECTS) def config = configBuilder.build() def generator = new com.github.victools.jsonschema.generator.SchemaGenerator(config) def schemaFolder = file('schemas') schemaFolder.mkdirs() def schemaMap = [ com.mypackage.MyClass: 'my-class.schema' ] schemaMap.each { clazz, fileName -> def jsonSchema = generator.generateSchema(clazz) def outputFile = new File(schemaFolder, fileName) outputFile.text = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema) } } } processResources.finalizedBy generateJsonSchema
这个方案的好处是不用额外维护Java类,但脚本复杂度稍高,适合简单的生成逻辑场景。
注意事项
- 确保jsonschema-generator和Jackson的依赖已正确配置,无论是Java类的依赖还是Gradle buildscript的依赖
- 可以调整
SCHEMA_FOLDER路径,比如改成src/main/resources/schemas,这样生成的Schema会被自动打包到jar中 - 如果
MyClass有其他依赖,要确保这些依赖在任务的classpath中可用
内容的提问来源于stack exchange,提问作者Vlad Schnakovszki
相关产品推荐
相关产品推荐

