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

如何实现带最小小数位数配置的BigDecimal JSON序列化注解?

基于自定义注解实现可配置的BigDecimal金额序列化方案

1. 自定义带参数的序列化配置注解

创建@MoneySerialize注解,用于传递字段序列化时的最小保留小数位数参数:

import com.fasterxml.jackson.annotation.JacksonAnnotation;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface MoneySerialize {
    // 最小保留小数位数,默认值为0
    int minimumScale() default 0;
}

2. 实现可读取注解参数的MoneySerializer

修改原有序列化器,使其能读取字段上的注解参数,并按规则处理BigDecimal格式化:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;

public class MoneySerializer extends StdSerializer<BigDecimal> {

    public MoneySerializer() {
        super(BigDecimal.class);
    }

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (value == null) {
            gen.writeNull();
            return;
        }

        // 读取字段上的@MoneySerialize注解参数
        int minimumScale = 0;
        var activeProperty = provider.getActiveProperty();
        if (activeProperty != null) {
            MoneySerialize annotation = activeProperty.getAnnotation(MoneySerialize.class);
            if (annotation != null) {
                minimumScale = annotation.minimumScale();
            }
        }

        // 去除末尾多余零
        BigDecimal strippedValue = value.stripTrailingZeros();
        int currentScale = strippedValue.scale();

        // 保证保留至少指定的最小小数位数
        if (currentScale < minimumScale) {
            strippedValue = strippedValue.setScale(minimumScale, RoundingMode.UNNECESSARY);
        }

        // 输出为普通字符串(避免科学计数法)
        gen.writeString(strippedValue.toPlainString());
    }
}

3. 在POJO字段上配置注解

在MoneyBean的字段上同时指定序列化器和自定义配置注解:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.math.BigDecimal;

public class MoneyBean {

    // 保留至少2位小数,去除多余尾零:100.0000 → 100.00
    @JsonSerialize(using = MoneySerializer.class)
    @MoneySerialize(minimumScale = 2)
    private BigDecimal amount1;

    // 去除所有尾零:100.0000 → 100;100.1000 → 100.1
    @JsonSerialize(using = MoneySerializer.class)
    @MoneySerialize(minimumScale = 0)
    private BigDecimal amount2;

    // 构造方法、Getter、Setter省略
}

核心逻辑说明

  • 去除尾零:通过stripTrailingZeros()移除BigDecimal末尾的无效零,得到最精简的数值表示
  • 最小小数位保证:对比去除尾零后的小数位数与注解指定的minimumScale,若前者更小则补零到指定位数(使用RoundingMode.UNNECESSARY避免四舍五入,保证精度)
  • 字符串输出:使用toPlainString()避免BigDecimal自动转为科学计数法的情况

内容的提问来源于stack exchange,提问作者luke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:10:30