SpringBoot 接口返回long类型数据注意点
所属分类 springboot
浏览量 16
SpringBoot 接口中返回long类型数据注意点
最常见的问题是跨语言(Java→JavaScript)的精度丢失,
建议对超过2^53的long值统一转为字符串返回,避免前后端数据不一致。
JavaScript 数字精度问题JavaScript 的Number类型是 64 位双精度浮点数,只能精确表示小于2^53(即 9007199254740992)的整数
如果long值超过这个范围,前端接收后会出现精度丢失(例如后端返回1234567890123456789,前端可能显示为1234567890123456800)
解决方案:
接口返回时将long转为String类型
使用 Jackson 的@JsonSerialize注解指定序列化方式:
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
全局配置 Jackson 将所有long转为字符串(避免逐个字段配置)
数据库字段映射
若数据库字段为BIGINT(对应 Java 的long),注意避免使用int接收(可能导致溢出)
主键自增场景下,long类型更适合存储大数值 ID(如雪花算法生成的 ID)
包装类型与基本类型选择
接口返回Long(包装类型)时可能为null,前端需处理空值情况
返回long(基本类型)时默认值为0,需注意业务逻辑中0是否为合法值
JSON 序列化配置当使用 Jackson 作为默认序列化工具时,可通过全局配置统一处理long类型:
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 所有Long类型转为String
SimpleModule module = new SimpleModule();
// Long类型 转成字符串
module.addSerializer(Long.class, ToStringSerializer.instance);
// long类型 转成字符串
module.addSerializer(long.class, ToStringSerializer.instance);
mapper.registerModule(module);
return mapper;
}
}
接口文档说明在 Swagger 等接口文档中明确标注long字段的取值范围,提醒前端注意精度问题,尤其是 ID 类字段
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.pig4cloud.pig.common.core.jackson.PigJavaTimeModule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import java.time.ZoneId;
import java.util.Locale;
import java.util.TimeZone;
@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfiguration {
@Bean
@ConditionalOnMissingBean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
builder.locale(Locale.CHINA);
builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
// Long类型 转成字符串
builder.serializerByType(Long.class, ToStringSerializer.instance);
// long类型 转成字符串
builder.serializerByType(long.class, ToStringSerializer.instance);
builder.modules(new DemoJavaTimeModule());
};
}
}
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.PackageVersion;
import com.fasterxml.jackson.datatype.jsr310.deser.*;
import com.fasterxml.jackson.datatype.jsr310.ser.*;
import java.time.*;
import java.time.format.DateTimeFormatter;
//java 8 时间默认序列化
public class DemoJavaTimeModule extends SimpleModule {
public PigJavaTimeModule() {
super(PackageVersion.VERSION);
// ======================= 时间序列化规则 ===============================
// yyyy-MM-dd HH:mm:ss
this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DatePattern.NORM_DATETIME_FORMATTER));
// yyyy-MM-dd
this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
// HH:mm:ss
this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
// Instant 类型序列化
this.addSerializer(Instant.class, InstantSerializer.INSTANCE);
// Duration 类型序列化
this.addSerializer(Duration.class, DurationSerializer.INSTANCE);
// ======================= 时间反序列化规则 ==============================
// yyyy-MM-dd HH:mm:ss
this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DatePattern.NORM_DATETIME_FORMATTER));
// yyyy-MM-dd
this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
// HH:mm:ss
this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME));
// Instant 反序列化
this.addDeserializer(Instant.class, InstantDeserializer.INSTANT);
// Duration 反序列化
this.addDeserializer(Duration.class, DurationDeserializer.INSTANCE);
}
}
上一篇
微信公众号如何获得收益
DIV 文字 水平垂直居中
文字红色填充、黑色边框效果 css写法