Jackson自定义序列化器、反序列化器【用于处理价格精度问题】

打个比方: 用户看到的金钱数值都是保留两位的,但是实际service计算、存储在DB中的数值都是保留多位的,【至于四舍五入还是奇进偶不进就结合具体的业务处理】最后扣款是扣除两位小数

假如所有和价格相关的属性都在service层自己进行倍数的放大和缩小,代码显得十分的冗余!毕竟不是主业务代码,次业务代码都要想方设法的抽取出来!

例如 在数据库中存储都是四位小数的存储,在service层都是四位小数的运算,最后的输出结果使用序列化器,缩小10000倍,交给前端保留两位小数显示。

配置Jackson自定义序列化器、反序列化器

public class MoneyDeserializer extends StdDeserializer<Long> {
    public MoneyDeserializer() {
        this(null);
    }

    public MoneyDeserializer(Class<?> vc) {
        super(vc);
    }

    /**
     * 金额反序列化
     * 小数 -> Long
     * 保留四位小数,放大10000倍
     */
    @Override
    public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String text = p.getText().trim();
        double v = Double.parseDouble(text);
        return (long) (v * 10000);
    }
}
public class MoneySerializer extends StdSerializer<Long> {
    public MoneySerializer() {
        this(null);
    }

    public MoneySerializer(Class<Long> t) {
        super(t);
    }

    /**
     * 金额序列化
     * Long -> 小数
     * 缩小10000倍
     */
    @Override
    public void serialize(Long value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        BigDecimal result = new BigDecimal(value.toString()).divide(new BigDecimal("10000"), 4, BigDecimal.ROUND_HALF_EVEN);
        gen.writeNumber(result.toPlainString());
    }
}

使用Jackson自定义序列化器、反序列化器

  • VO接收参数,将金钱数值放大10000倍
@Data
public class CreateNormalVO {
    @NotNull(message = "产品标价最小值不能为空")
    @JsonDeserialize(using = MoneyDeserializer.class)
    private Long productPriceMin;
    @NotNull(message = "产品标价最大值不能为空")
    @JsonDeserialize(using = MoneyDeserializer.class) 
}
  • 将service层处理完的entity赋值给 下面这个输出的VO,将金钱数值缩小10000倍给前端保留两位显示处理
@Data
public class OutputNormalProductVO {

    @JsonSerialize(using = MoneySerializer.class)
    protected Long productPriceMin;
    @JsonSerialize(using = MoneySerializer.class)
    protected Long productPriceMax;

}

原文地址:https://www.cnblogs.com/chenyiwu/p/14413721.html