一.抛出问题:
现在的项目中,存在这样的几个问题:
问题一.数据库存的数据类型是BigDecimal,或者代码中计算需要返回BigDecimal的值,由于BigDecimal返回给前端可能存在精度丢失情况
问题二.BigDecimal再后台计算后,通常需要保留两位小数或者三位小数返回给前端,每个数据都需要处理,代码太过于冗余;
二.解决方式:
问题一的解决方案:
使用全局的序列化配置,统一将BigDecimal的数据类型转换为String类型,前端将String解析为小数即可;
代码如下
package com.gabriel.stage.config; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import com.google.common.collect.ImmutableList; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.List; /** * @author Gabriel * @date 2020-01-08 * @description 自定义SpringMvc转换器 解决数据转换问题(例如BigDecimal转换为String,解决精度问题) * 注意:springboot2.x以后继承 WebMvcConfigurationSupport 会覆盖"所有的WebMvc默认的配置,比如WebMvcConfigure",因此不推荐该中方法 */ //@Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { /** * Date格式化字符串 */ private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); /** * DateTime格式化字符串 */ private static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); /** * Time格式化字符串 */ private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss"); @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = converter.getObjectMapper(); // 反序列化失败 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // long 转换为字符串 SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); // 浮点型使用字符串 simpleModule.addSerializer(Double.class, ToStringSerializer.instance); simpleModule.addSerializer(Double.TYPE, ToStringSerializer.instance); simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); // java8 时间格式化 simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATETIME_FORMAT)); simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer(DATE_FORMAT)); simpleModule.addSerializer(LocalTime.class, new LocalTimeSerializer(TIME_FORMAT)); objectMapper.registerModule(simpleModule); // 为mapper注册一个带有SerializerModifier的Factory,处理null值 objectMapper.setSerializerFactory(objectMapper.getSerializerFactory() //CustomizeBeanSerializerModifier 自定义序列化修改器 .withSerializerModifier(new CustomizeBeanSerializerModifier())); // 处理中文乱码问题 converter.setSupportedMediaTypes(ImmutableList.of(MediaType.APPLICATION_JSON_UTF8)); converter.setObjectMapper(objectMapper); converters.add(converter); converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); } }
问题二的解决方案:
自定义序列器,使用 @JsonSerialize(using = 自定义序列化器类.class)去序列化指定的属性
代码如下
package com.in.g.data.config; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.math.BigDecimal; /** * @author: Gabriel * @date: 2020/3/7 15:28 * @description 小数保留2位返回给前端序列化器 */ public class Decimal2Serializer extends JsonSerializer<Object> { /** * 将返回的BigDecimal保留两位小数,再返回给前端 * @param value * @param jsonGenerator * @param serializerProvider * @throws IOException * @throws JsonProcessingException */ @Override public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { if (value != null) { BigDecimal bigDecimal = new BigDecimal(value.toString()).setScale(2,BigDecimal.ROUND_HALF_UP); jsonGenerator.writeString(bigDecimal.toString()); } } }
package com.gabriel.stage.vo; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.gabriel.stage.config.Decimal2Serializer; import lombok.Data; import java.math.BigDecimal; /** * @author: Gabriel * @date: 2020/3/7 15:45 * @description */ @Data public class TestVO { @JsonSerialize(using = Decimal2Serializer.class) private BigDecimal bigDecimal; }