天天看點

解決後端傳輸純數字字元串JS精度缺失問題

問題描述:

後端代碼傳回值為String,但是這個字元串為純數字!!!純數字,實際上是雪花算法生成的Long類型的辨別,但是因為某些原因我進行了稍微的修改,使資料标志占高五位,造成生成的ID超過本來的長度,繼而造成了後續的一系列問題(在保證接口傳回值類型不變的情況下保證新舊版本都能擷取到傳回值而不是精度缺失後兩位變成0)

問題解決:

  • 強行變成字元(傳回值為String類型,即ID)

    這個方法是我在查找問題的時候使用的。

    我能夠確定後端接口傳回值沒有問題,傳回值也是String類型,但是到前端會自動變成number類型資料(

    console.log(typeof(res.data))

    測出來的),心裡一萬頭草泥馬奔過,為了最快速的解決,我決定強行轉String!!
    @RequestMapping(value = "csdn", consumes = "application/json;charset=UTF-8")
    public String csdn(@RequestBody String c) {
    	log.info("調用Service接口,傳回String類型資料");
    	// 假設是service調用傳回值
    	String id = "1441163676357369856";
    //	return id;// 此時傳回前端res.data展示為1441163676357369900,被當做number處理,造成精度缺失
    	return "\"" + id + "\"";// 強行轉成String,硬加  " 字元,前端當做字元串,無問題
    }
               
    然而這個方法太不友善,好多接口都要改(怪就怪自己資料庫屬性設定是varchar而不是long)。
  • 設定序列化規則

    此種情況傳回值為Long類型資料(資料庫以及實體類慎重選擇)

    @RequestMapping(value = "csdn", consumes = "application/json;charset=UTF-8")
    public Long csdn(@RequestBody String c) {
    	log.info("調用Service接口,傳回String類型資料");
    	// 假設是service調用傳回值
    	String id = "1441163676357369856";
    	return Long.parseLong(id);// 傳回Long類型資料
    }
               

    在不改動已完成service接口情況下,為了防止之後再次發生此種情況,後續資料庫表字段設定為long類型,直接傳回Long類型資料,不需要再轉一次。

    下面配置,設定所有的Long類型轉成String傳給前端

    package org.pet.king.config;
    
    import java.math.BigInteger;
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
    
    @Configuration
    public class WebMvcConfig extends WebMvcConfigurationSupport {
    	/**
    	 * 解決傳回值亂碼問題
    	 */
    	@Bean
    	public HttpMessageConverter<String> responseBodyStringConverter() {
    		StringHttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
    		return converter;
    	}
    	/**
    	 * 修改StringHttpMessageConverter預設配置
    	 * @param converters
    	 */
    	@Override
    	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    		converters.add(responseBodyStringConverter());
    		MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
    		ObjectMapper objectMapper = new ObjectMapper();
    		SimpleModule simpleModule = new SimpleModule();
    		/**
    		 * 将Long,BigInteger序列化的時候,轉化為String,某些類裡面的Long類型資料超長造成精度缺失可以在屬性上使用@JsonSerialize注解
    		 */
    		simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    		simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
    		simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
    		objectMapper.registerModule(simpleModule);
    		messageConverter.setObjectMapper(objectMapper);
    		converters.add(messageConverter);
    	}
    }
               
    至此,資料傳到前端debugger的時候會帶

    ""

    ,不會再出現精度缺失情況,個人建議資料傳輸盡量選擇String,Long類型的資料可以通過getString拿到,但是String不能通過getLong擷取。