You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过自定义注解实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 23:15:31