Avro Schema字段设置别名编译为Java类后无对应getter/setter的使用问题
关于Avro字段别名的使用说明
1. 先纠正Schema的写法问题
你当前使用的单数字段别名属性alias不符合Avro官方规范,标准的别名属性是复数aliases,值为字符串数组,正确写法如下:
{ "type": "record", "name": "Tests", "fields": [ { "name": "name", "aliases": ["first_name"], "type": "string", "default": "" } ] }
2. 为什么生成的Java类没有别名对应的get/set方法
Avro的字段别名设计初衷是解决不同版本Schema之间的序列化/反序列化兼容性问题,而非为同Schema下的对象构造提供别名语法糖,因此官方默认的代码生成器不会为别名生成额外的存取方法。
3. 如何用别名构造Avro记录
方案1:使用GenericRecord操作(推荐)
GenericRecord天然支持通过别名读写字段,使用方式如下:
import org.apache.avro.Schema; import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericRecord; import org.apache.avro.specific.SpecificData; // 获取你的Schema Schema schema = Tests.getClassSchema(); // 构造GenericRecord GenericRecord record = new GenericData.Record(schema); // 直接用别名赋值 record.put("first_name", "张三"); // 如果需要转成生成的Specific类Tests Tests tests = (Tests) SpecificData.get().deepCopy(schema, record); // 此时用getName就能拿到值 System.out.println(tests.getName()); // 输出:张三
方案2:手动封装别名存取工具类
如果必须使用生成的Specific类,可以自己写工具类封装别名操作,避免直接修改自动生成的代码(重新生成会覆盖修改):
public class TestsUtils { public static void setFirstName(Tests tests, String firstName) { tests.setName(firstName); } public static String getFirstName(Tests tests) { return tests.getName() == null ? null : tests.getName().toString(); } }
方案3:自定义代码生成模板
如果需要批量为所有别名生成对应get/set方法,可以修改Avro代码生成器的Velocity模板,在生成类的时候自动扫描字段的aliases属性,生成对应的存取方法,适合项目有大量别名需要支持的场景。
额外说明
如果你是要读取上游使用first_name作为字段名的旧Avro数据,不需要额外操作:只要你当前的Schema为name字段配置了first_name作为别名,Avro反序列化器会自动将旧数据的first_name值映射到name字段,你直接调用getName()就能拿到对应值。
内容的提问来源于stack exchange,提问作者Sammy
相关产品推荐
相关产品推荐

