如何在Maven构建中将.avsc Avro Schema文件转换为.avdl文件?
在Maven构建流程中实现Avsc到Avdl格式的转换方案
针对你提到的现有插件限制,我们可以借助Avro的原生Java API,结合Maven的通用执行类插件或脚本插件来实现转换,以下是两种可行方案:
方案一:使用Groovy Maven插件编写转换脚本
Groovy脚本可以直接调用Avro API,无需额外编译Java类,适合快速实现转换逻辑。
1. 在pom.xml中配置Groovy Maven插件
<build> <plugins> <plugin> <groupId>org.codehaus.gmavenplus</groupId> <artifactId>gmavenplus-plugin</artifactId> <version>1.13.1</version> <executions> <execution> <id>convert-avsc-to-avdl</id> <phase>generate-sources</phase> <goals> <goal>execute</goal> </goals> <configuration> <scripts> <script>${project.basedir}/src/main/groovy/AvscToAvdlConverter.groovy</script> </scripts> <properties> <inputDir>${project.basedir}/src/main/resources/avsc</inputDir> <outputDir>${project.basedir}/target/generated-resources/avdl</outputDir> </properties> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.11.3</version> </dependency> </dependencies> </plugin> </plugins> </build>
2. 编写Groovy转换脚本 AvscToAvdlConverter.groovy
import org.apache.avro.Schema import org.apache.avro.Schema.Type def inputDir = new File(properties.inputDir) def outputDir = new File(properties.outputDir) outputDir.mkdirs() inputDir.eachFileMatch(~/.*\.avsc/) { file -> def schema = new Schema.Parser().parse(file) def avdlContent = generateAvdl(schema) def outputFile = new File(outputDir, "${schema.getName()}.avdl") outputFile.write(avdlContent, "UTF-8") println "Converted ${file.name} to ${outputFile.name}" } String generateAvdl(Schema schema) { def sb = new StringBuilder() // 写入命名空间 if (schema.getNamespace()) { sb.append("namespace ${schema.getNamespace()};\n\n") } // 写入类型定义 sb.append("protocol ${schema.getName()}Protocol {\n") sb.append(" ${generateTypeDefinition(schema)}\n") sb.append("}\n") return sb.toString() } String generateTypeDefinition(Schema schema) { switch (schema.getType()) { case Type.RECORD: def fields = schema.getFields().collect { field -> " ${field.name()}: ${getTypeString(field.schema())};" }.join("\n") return "record ${schema.getName()} {\n${fields}\n }" case Type.ENUM: def symbols = schema.getEnumSymbols().join(", ") return "enum ${schema.getName()} {\n ${symbols}\n }" case Type.UNION: return schema.getTypes().collect { getTypeString(it) }.join(" | ") default: return schema.getType().name().toLowerCase() } } String getTypeString(Schema schema) { if (schema.getType().name() in ['RECORD', 'ENUM']) { return schema.getFullName() } else if (schema.getType() == Type.ARRAY) { return "array<${getTypeString(schema.getElementType())}>" } else if (schema.getType() == Type.MAP) { return "map<${getTypeString(schema.getValueType())}>" } else if (schema.getType() == Type.UNION) { return schema.getTypes().collect { getTypeString(it) }.join(" | ") } else { return schema.getType().name().toLowerCase() } }
这个脚本会遍历指定目录下的所有.avsc文件,解析后生成对应的Avdl协议文件,包含基本的记录、枚举、联合类型等转换逻辑,可根据你的schema复杂度扩展。
方案二:自定义Java工具类 + Maven Exec插件
如果更习惯Java开发,可以编写一个工具类实现转换,再用Exec插件调用。
1. 编写Java转换工具类
import org.apache.avro.Schema; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class AvscToAvdlConverter { public static void main(String[] args) throws IOException { String inputDirPath = args[0]; String outputDirPath = args[1]; File inputDir = new File(inputDirPath); File outputDir = new File(outputDirPath); if (!outputDir.exists()) { outputDir.mkdirs(); } for (File file : inputDir.listFiles((dir, name) -> name.endsWith(".avsc"))) { Schema schema = new Schema.Parser().parse(file); String avdlContent = generateAvdl(schema); File outputFile = new File(outputDir, schema.getName() + ".avdl"); try (FileWriter writer = new FileWriter(outputFile)) { writer.write(avdlContent); } System.out.println("Converted " + file.getName() + " to " + outputFile.getName()); } } private static String generateAvdl(Schema schema) { StringBuilder sb = new StringBuilder(); if (schema.getNamespace() != null) { sb.append("namespace ").append(schema.getNamespace()).append(";\n\n"); } sb.append("protocol ").append(schema.getName()).append("Protocol {\n"); sb.append(" ").append(generateTypeDefinition(schema)).append("\n"); sb.append("}\n"); return sb.toString(); } private static String generateTypeDefinition(Schema schema) { switch (schema.getType()) { case RECORD: StringBuilder fieldsSb = new StringBuilder(); for (Schema.Field field : schema.getFields()) { fieldsSb.append(" ").append(field.name()).append(": ") .append(getTypeString(field.schema())).append(";\n"); } return "record " + schema.getName() + " {\n" + fieldsSb + " }"; case ENUM: String symbols = String.join(", ", schema.getEnumSymbols()); return "enum " + schema.getName() + " {\n " + symbols + "\n }"; case UNION: return String.join(" | ", schema.getTypes().stream().map(AvscToAvdlConverter::getTypeString).toList()); default: return schema.getType().name().toLowerCase(); } } private static String getTypeString(Schema schema) { return switch (schema.getType()) { case RECORD, ENUM -> schema.getFullName(); case ARRAY -> "array<" + getTypeString(schema.getElementType()) + ">"; case MAP -> "map<" + getTypeString(schema.getValueType()) + ">"; case UNION -> String.join(" | ", schema.getTypes().stream().map(AvscToAvdlConverter::getTypeString).toList()); default -> schema.getType().name().toLowerCase(); }; } }
2. 在pom.xml中配置Exec插件
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>convert-avsc-to-avdl</id> <phase>generate-sources</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.yourpackage.AvscToAvdlConverter</mainClass> <arguments> <argument>${project.basedir}/src/main/resources/avsc</argument> <argument>${project.basedir}/target/generated-resources/avdl</argument> </arguments> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.11.3</version> </dependency> </dependencies> </plugin> </plugins> </build>
注意事项
- 确保Avro依赖版本与你的项目一致,避免兼容性问题
- 上述代码支持基本的Avro类型转换,若你的schema包含复杂嵌套、自定义逻辑,可扩展
generateTypeDefinition方法 - 转换后的Avdl文件会输出到
target/generated-resources/avdl目录,可根据需求调整路径
内容的提问来源于stack exchange,提问作者Harold L. Brown
相关产品推荐
相关产品推荐

