解决java后端序列化后传前端数据不一致/不匹配,比如Long类型或者LocalDateTime类型
解决java后端序列化后传前端数据不一致/不匹配,比如Long类型或者LocalDateTime类型
1.原因
后端在向前端发送long类型的数据时,会发生精度改变
当后端传Long类型给前端, Long类型数据大于17位时。前端拿到的数据: 第16位会四舍五入, 17位后的数据自动用0代替),在Json中就会出现精度丢失的情况。
2.解决方法
(1)用String代替Long:
这种方式代价太大,数据库的id类型一般都会是bigint,对应Java中Long。
所以修改后需要修改很多地方。
(2)不修改Long类型,只在进行Json序列化时,以String的形式去序列化:
这种方式对原有代码不需要修改。
a. 使用FastJson的字段Json序列化方式(个人使用这个,比较好用)
1.在相关配置类里增加对象映射器配置
com/wwk/config/JacksonObjectMapper.java
package com.wwk.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.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
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 org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
说明:
这里是引用这是一个继承自ObjectMapper的自定义JacksonObjectMapper类的实现,其中对ObjectMapper进行了一些自定义配置。
在构造函数中,将FAIL_ON_UNKNOWN_PROPERTIES设置为false,表示在收到未知属性时不会抛出异常。
取消DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES特性,以兼容反序列化时属性不存在的情况。
添加了一个SimpleModule,并注册了一些自定义的序列化器和反序列化器:
LocalDateTime、LocalDate、LocalTime的反序列化器,使用DateTimeFormatter解析默认的日期时间格式字符串。
BigInteger、Long、LocalDateTime、LocalDate、LocalTime的序列化器,将它们序列化为字符串。
最后,将这个SimpleModule注册到ObjectMapper中。
这个JacksonObjectMapper类的作用是用于将Java对象序列化为JSON字符串或者将JSON字符串反序列化为Java对象。它可以应用于Spring MVC中,例如在Spring Boot中将其注册为一个Bean,以便在整个应用程序中共享此配置。
2.在Web应用程序配置类里加入转换器对象
com/wwk/config/WebMvcConfig.java
package com.wwk.config;
//import com.itheima.reggie.common.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
/**
* @author swh
* @creat 2022/7/28
*/
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 扩展mvc框架的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器");
//创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
//设置对象转换器,底层使用jackson将java对象转为json
messageConverter.setObjectMapper(new JacksonObjectMapper());
//将上面的消息转换器对象追加到mvc框架的转换器集合中
converters.add(0,messageConverter);
}
}
b. 使用SpringBoot的字段Json序列化方式:
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
更多推荐
所有评论(0)