Jackson自定义BigDecimal序列化时的精度
需求:接口中返回数字时需要对数字进行保留小数的处理。
解决方法:实现一个BigDecimalSerializer,以及一个@BigDecimalScale注解,可实现自定义的数字精度。
代码:
BigDecimalWithAccuracySer类:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.math.BigDecimal;
/**
* bigDecimal转成字符串,可识别精度
*/
public class BigDecimalWithAccuracySer extends StdSerializer<BigDecimal> implements ContextualSerializer {
private final BigDecimalScale annotation;
public BigDecimalWithAccuracySer(Class<BigDecimal> t, BigDecimalScale annotation) {
super(t);
this.annotation = annotation;
}
public BigDecimalWithAccuracySer(Class<BigDecimal> t) {
super(t);
this.annotation = null;
}
public BigDecimalWithAccuracySer(JavaType type) {
super(type);
this.annotation = null;
}
public BigDecimalWithAccuracySer(Class<?> t, boolean dummy) {
super(t, dummy);
this.annotation = null;
}
public BigDecimalWithAccuracySer(StdSerializer<?> src) {
super(src);
this.annotation = null;
}
@Override
public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider provider) throws IOException {
if (annotation == null) {
gen.writeNumber(value.toPlainString());
} else {
BigDecimal decimal = value
.movePointLeft(annotation.moveLeft())
.movePointRight(annotation.moveRight())
.setScale(annotation.setScale(), annotation.setRoundingMode());
gen.writeNumber(decimal.toPlainString());
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
BigDecimalScale annotation = property.getAnnotation(BigDecimalScale.class);
return new BigDecimalWithAccuracySer(BigDecimal.class, annotation);
}
}
ContextualSerializer接口的作用是创建一个可感知当前处理字段相关信息的Serializer。其createContextual可自定义创建的Serializer。
BigDecimalScale注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.RoundingMode;
/**
* 配合BigDecimalWithAccuracySer,处理bigDecimal的精度
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BigDecimalScale {
/**
* 设置小数点精度
*/
int setScale() default 0;
/**
* 设置保留方式
*/
RoundingMode setRoundingMode() default RoundingMode.HALF_UP;
/**
* 左移位数
*/
int moveLeft() default 0;
/**
* 右移位数
*/
int moveRight() default 0;
}
配置ObjectMapper:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.math.BigDecimal;
import java.util.TimeZone;
@Configuration
public class ObjectMapperConfigure {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(BigDecimal.class, new BigDecimalWithAccuracySer(BigDecimal.class));
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}

浙公网安备 33010602011771号