JAVA中关于Long类型返回前端精度丢失问题处理

昀贝 2024-09-06 17:03:01 阅读 59

 问题出现:

新项目将后端的Java Bean的id属性是用的Long类型对应数据库主键使用bigint类型,id改为雪花后出现的异常问题,比如id:1799633456368132098返回错误的id:1799633456368132000。导致明显问题数值精度丢失。后三位数值转换为0了。

问题原因:

Java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值),导致Id最后几位直接变成了0。

解决方案一

1、将后端id字段类型换位字符串类型,并且前端以字符串的方式接收就不会有精度丢失了。

2、单个字段注释,这只需要我们在需要转换的字段上增加@JsonSerialize(using=ToStringSerializer.class)注解

解决方案二

SpringBoot使用Jackson序列化方式

<code>需要引入依赖

<dependency>

<groupId>com.fasterxml.jackson.datatype</groupId>

<artifactId>jackson-datatype-jsr310</artifactId>

</dependency>

package com.znkj.nvm.common.config;

import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;

import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.annotation.Order;

import java.math.BigDecimal;

import java.math.BigInteger;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

import java.util.TimeZone;

/**

* jackson 配置

* 加载顺序:-10000

**/

@Slf4j

@Order(-10000)

@Configuration

public class JacksonConfig {

@Bean

public Jackson2ObjectMapperBuilderCustomizer customizer() {

return builder -> {

// 全局配置序列化返回 JSON 处理

JavaTimeModule javaTimeModule = new JavaTimeModule();

javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);

javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);

javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);

javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));

javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));

builder.modules(javaTimeModule);

builder.timeZone(TimeZone.getDefault());

log.info("初始化 jackson 配置");

};

}

}

package com.gyq.common.config;

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.databind.SerializerProvider;

import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;

import com.fasterxml.jackson.databind.ser.std.NumberSerializer;

import java.io.IOException;

/**

* 超出 JS 最大最小值 处理

**/

@JacksonStdImpl

public class BigNumberSerializer extends NumberSerializer {

/**

* 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来

*/

private static final long MAX_SAFE_INTEGER = 9007199254740991L;

private static final long MIN_SAFE_INTEGER = -9007199254740991L;

/**

* 提供实例

*/

public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);

public BigNumberSerializer(Class<? extends Number> rawType) {

super(rawType);

}

@Override

public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {

// 超出范围 序列化位字符串

if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {

super.serialize(value, gen, provider);

} else {

gen.writeString(value.toString());

}

}

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。