JSON转Long类型时精度丢失问题解决

这个问题的原因是js在对长整型数据进行处理时会损失精度, 从而id发生变化。

要想解决这个问题,也很简单,只需要让js处理的ID数据类型为字符串类型即可, 这样就不会损失精度了

问题修复

1、JacksonObjectMapper

reggie-common模块下创建com.itheima.reggie.common.JacksonObjectMapper,自定义映射规则


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;

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 JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(FAIL_ON_UNKNOWN_PROPERTIES);

        //自定义转换规则
        SimpleModule simpleModule = new SimpleModule()
                .addSerializer(BigInteger.class, ToStringSerializer.instance)//将BigInteger转换为String
                .addSerializer(Long.class, ToStringSerializer.instance);//将Long转换成String
        this.registerModule(simpleModule);
    }
}

或是:将其存入springbean中 即 加一个 @Component


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.stereotype.Component;

import java.math.BigInteger;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

@Component
public class JacksonObjectMapper extends ObjectMapper {
    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(FAIL_ON_UNKNOWN_PROPERTIES);

        //自定义转换规则
        SimpleModule simpleModule = new SimpleModule()
                .addSerializer(BigInteger.class, ToStringSerializer.instance)//将BigInteger转换为String
                .addSerializer(Long.class, ToStringSerializer.instance);//将Long转换成String
        this.registerModule(simpleModule);
    }
}

 

2、WebMvcConfig

com.itheima.reggie.config.ReggieWebMvcConfig中添加下面代码  

 //扩展mvc框架的消息转换器
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0, messageConverter);
    }

完整的WebMvcConfig类的代码:

package com.itheima.reggie.config;

import com.itheima.reggie.common.JacksonObjectMapper;
import com.itheima.reggie.interceptors.CheckLoginInterceptors;
import org.springframework.beans.factory.annotation.Autowired;
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.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName ReggieWebManageWebConfigurer
 * @Description 后台管理的webmvc的配置类
 * @Author LPS
 * @Date 2023/7/31 21:51
 */
@Configuration
public class ReggieWebManageWebConfigurer implements WebMvcConfigurer {

    //登录拦截器
    @Autowired
    private CheckLoginInterceptors checkLoginInterceptors;
    /**
     * 指定静态资源加载位置
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //当访问请求是/backend/**时,去classpath:/backend/寻找对应资源
        // Handler --相当-- 前端路径 ,Locations --相当-- 后端加载
        //Resource  资源
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
    }

    /*注册拦截器*/
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> stringList = new ArrayList<>();
        stringList.add("/employee/login");
        stringList.add("/employee/logout");
        stringList.add("/backend/**");
        stringList.add("/error");
        registry.addInterceptor(checkLoginInterceptors)  // 将拦截器添加到拦截列表
                .addPathPatterns("/**")   // 需要拦截的路径  这里是拦截所有
                .excludePathPatterns(stringList);  // 需要放行的路径
    }

    //扩展mvc框架的消息转换器
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0, messageConverter);
    }
}

或是:



import com.itheima.reggie.common.JacksonObjectMapper;
import com.itheima.reggie.interceptors.CheckLoginInterceptors;
import org.springframework.beans.factory.annotation.Autowired;
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.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class ReggieWebManageWebConfigurer implements WebMvcConfigurer {

    @Autowired
    private CheckLoginInterceptors checkLoginInterceptors;

    /**
     * 指定静态资源加载位置
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //当访问请求是/backend/**时,去classpath:/backend/寻找对应资源
        // Handler --相当-- 前端路径 ,Locations --相当-- 后端加载
        //Resource  资源
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
    }

    /*注册拦截器*/
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> stringList = new ArrayList<>();
        stringList.add("/employee/login");
        stringList.add("/employee/logout");
        stringList.add("/backend/**");
        stringList.add("/error");
        registry.addInterceptor(checkLoginInterceptors)  // 将拦截器添加到拦截列表
                .addPathPatterns("/**")   // 需要拦截的路径  这里是拦截所有
                .excludePathPatterns(stringList);  // 需要放行的路径
    }

    //  自定义数据类型转换器
    @Autowired
    private JacksonObjectMapper jacksonObjectMapper;

    //扩展mvc框架的消息转换器
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(jacksonObjectMapper);
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0, messageConverter);
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在将 JSON 换为 List 实体类对象,如果 JSON 中包含 long 类型字段,可以使用 Gson 库进行处理。Gson 库是一个 Google 开发的用于处理 JSON 格式数据的 Java 库,支持将 JSON 字符串化为 Java 对象,并且可以通过注解配置来实现灵活的换。 在使用 Gson 库,需要将 long 类型换为字符串类型,避免精度丢失。可以通过自定义 Gson 换器来实现类型换。具体实现如下: 1. 定义实体类对象: ```java public class User { private String name; private long id; // getter 和 setter 方法 } ``` 2. 使用 Gson 换器将 JSON 换为 List<User> 对象: ```java Gson gson = new GsonBuilder() .registerTypeAdapter(User.class, new JsonDeserializer<User>() { @Override public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); User user = new User(); user.setName(jsonObject.get("name").getAsString()); String idStr = jsonObject.get("id").getAsString(); user.setId(Long.parseLong(idStr)); return user; } }) .create(); String jsonStr = "[{\"name\":\"张三\",\"id\":1001},{\"name\":\"李四\",\"id\":1002}]"; Type userListType = new TypeToken<List<User>>() {}.getType(); List<User> userList = gson.fromJson(jsonStr, userListType); ``` 在上面的代码中,我们通过 `registerTypeAdapter` 方法注册了一个自定义的 `JsonDeserializer<User>` 类型换器,重写了 `deserialize` 方法来实现 long 类型字段的换。通过 `JsonElement` 和 `JsonObject` 对象获取 JSON 中的字段值,并将 long 类型字段换为字符串类型后再进行解析。 最后,我们使用 `fromJson` 方法将 JSON 字符串换为 List<User> 对象。 注意:在使用 Gson 库,需要添加 Gson 依赖。可以通过 Gradle 或 Maven 等构建工具来添加依赖,例如: Gradle: ```groovy dependencies { implementation 'com.google.code.gson:gson:2.8.6' } ``` Maven: ```xml <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> </dependency> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值