首页  

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写法