如何通过自定义注解实现POJO金额字段(Paise转Rupee)批量转换?
使用自定义注解实现金额自动转换(Paise → Rupee)
完全可行,自定义注解正是解决这类重复转换逻辑的绝佳方案——既能避免你之前遇到的「新增字段就要重写setter」的麻烦,还能把转换逻辑集中到一处,方便后续维护修改。
下面以最常见的JSON反序列化场景(对接第三方接口通常用JSON)为例,给你一步步实现方案:
1. 定义自定义注解
先写一个标记用的注解,用来标识哪些字段需要做Paise到Rupee的转换:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 仅允许标记在字段上 @Target(ElementType.FIELD) // 运行时保留注解,方便通过反射读取 @Retention(RetentionPolicy.RUNTIME) public @interface PaiseToRupee { // 可按需添加参数,比如是否允许空值、自定义转换比例,这里先做基础版 }
2. 实现自定义转换逻辑
以Jackson为例,写一个通用的反序列化器,负责把Paise数值转成Rupee:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; public class PaiseToRupeeDeserializer extends JsonDeserializer<Double> { @Override public Double deserialize(JsonParser parser, DeserializationContext context) throws IOException { // 读取第三方返回的Paise数值(通常为Long类型) Long paiseValue = parser.getLongValue(); // 转换规则:1 Rupee = 100 Paise return paiseValue != null ? paiseValue / 100.0 : null; } }
3. 绑定注解与转换器
为了让Jackson识别我们的注解,需要注册自定义模块。可以写一个ObjectMapper的配置类:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; public class CustomObjectMapper { public static ObjectMapper getMapper() { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 注册反序列化器,指定仅处理带@PaiseToRupee注解的字段 module.setDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { // 遍历当前类的所有字段 beanDesc.findProperties().forEach(prop -> { // 若字段带有目标注解,替换为自定义反序列化器 if (prop.getField().getAnnotation(PaiseToRupee.class) != null) { module.addDeserializer(Double.class, new PaiseToRupeeDeserializer()); } }); return super.modifyDeserializer(config, beanDesc, deserializer); } }); mapper.registerModule(module); return mapper; } }
4. 在POJO中使用注解
现在不管你的5个POJO里金额字段叫什么名字,只要给字段加上@PaiseToRupee注解就行,完全不用修改原有setter:
// 示例POJO1 public class Order { private String orderId; @PaiseToRupee private Double totalAmount; // 字段名是totalAmount,自动触发转换 // 普通的getter/setter,无需修改 } // 示例POJO2 public class Payment { private String transactionId; @PaiseToRupee private Double paymentValue; // 字段名是paymentValue,同样生效 // 普通的getter/setter,无需修改 }
其他场景的适配
如果不是JSON反序列化,比如是Spring MVC接收参数、JDBC结果集映射,思路也是类似的:
- Spring MVC:写一个
Converter<String, Double>,结合@InitBinder或全局转换器,通过反射判断字段是否带有注解再执行转换 - JDBC:自定义RowMapper,遍历POJO字段时检查注解,执行转换逻辑
核心优势
- 无侵入:POJO仅需添加注解,无需修改原有setter逻辑
- 易扩展:新增金额字段时,只需要加
@PaiseToRupee,不用重复写转换代码 - 易维护:转换逻辑集中在一处,后续调整规则(比如换转换比例、加异常处理),仅需修改转换器代码
内容的提问来源于stack exchange,提问作者Aakash Jha
相关产品推荐
相关产品推荐

