含java.lang.BigDecimal的POJO生成Avro Schema不符合预期问题
问题根因
这个报错不是操作失误,是Avro反射生成Schema的固有设计限制:
- Avro规范里的decimal逻辑类型强制要求显式传入precision(总精度)和scale(小数位数)两个必填参数,这两个值没有通用默认值——不同业务场景下的金额、计量数值对精度要求差异极大,官方不可能给出适配所有场景的默认配置,所以直接注册无参的
Conversions.DecimalConversion()时,反射流程拿不到这两个必填值,就会抛出你看到的No recommended schema for decimal (scale is required)异常。 - 官方自带的
DecimalConversion设计初衷,是配合已经明确定义好precision/scale的decimal Schema完成序列化、反序列化转换,并不是给无配置的反射自动生成Schema场景用的:比如你手写.avsc文件提前写死decimal的精度参数,或者用Avro的Specific编译器从avsc生成Java类时,字段上已经携带了精度配置,这时候DecimalConversion会正常完成二进制字节和BigDecimal对象的互转,不会触发报错。
存量POJO场景的低侵入解决方案
不需要全量手写所有Schema定义,两种改造成本极低的方案就能满足需求:
- 方案1:给BigDecimal字段加Avro原生注解指定精度
直接在对应字段上标记@AvroSchema注解,写入对应decimal的Schema配置即可,示例代码:
加完注解后沿用你原来的反射逻辑,注册public class TransactionEvent { private UUID transactionId; // 根据业务实际需要调整precision和scale值 @AvroSchema("{\"type\":\"bytes\",\"logicalType\":\"decimal\",\"precision\":18,\"scale\":2}") private BigDecimal total; // getter/constructor }DecimalConversion就能正常生成符合Avro官方规范、支持跨语言互通的decimal Schema,不会抛出异常。 - 方案2:扩展ReflectData自定义BigDecimal解析规则
如果项目里存量BigDecimal字段太多,逐个加注解改造成本高,可以自己继承ReflectData重写BigDecimal类型的Schema生成逻辑:比如配置全局默认的精度、小数位参数,或者读取自定义注解上的精度配置,统一生成符合规范的decimal Schema,再配合官方DecimalConversion完成序列化即可。
补充说明:你之前看到的Schema里携带
java-class字段的模式,是Avro的Java专属反射序列化模式,仅支持Java端读写,确实无法在多语言场景下互通,生产如果有非Java消费端不建议使用。
内容的提问来源于stack exchange,提问作者filpa
相关产品推荐
相关产品推荐

