• gson 反序列化,整数变小数的终极解决方案


    1.情景展示

    使用gson进行反序列化(json转java对象)的时候,你可能会遇到明明key对应的值是整数,而进行反序列化后,却变成了小数(后面加上了.0)。

    如何解决这个问题?

    2.具体分析

    准备工作

    查看代码
    /**
     * 数值类型实体类
     * @description: 包含整数和小数
     * @author: Marydon
     * @date: 2022-03-24 18:48
     * @version: 1.0
     * @email: marydon20170307@163.com
     */
    public class Number {
        private byte b;
        private short s;
        private int i;
        private long l;
        private double d;
        private float f;
        private Byte B2;
        private Short S2;
        private Integer I2;
        private Long L2;
        private Double D2;
        private Float F2;
        private BigDecimal bd;
        private BigInteger gi;
    
        public byte getB() {
            return b;
        }
    
        public void setB(byte b) {
            this.b = b;
        }
    
        public short getS() {
            return s;
        }
    
        public void setS(short s) {
            this.s = s;
        }
    
        public int getI() {
            return i;
        }
    
        public void setI(int i) {
            this.i = i;
        }
    
        public long getL() {
            return l;
        }
    
        public void setL(long l) {
            this.l = l;
        }
    
        public double getD() {
            return d;
        }
    
        public void setD(double d) {
            this.d = d;
        }
    
        public float getF() {
            return f;
        }
    
        public void setF(float f) {
            this.f = f;
        }
    
        public Byte getB2() {
            return B2;
        }
    
        public void setB2(Byte b2) {
            B2 = b2;
        }
    
        public Short getS2() {
            return S2;
        }
    
        public void setS2(Short s2) {
            S2 = s2;
        }
    
        public Integer getI2() {
            return I2;
        }
    
        public void setI2(Integer i2) {
            I2 = i2;
        }
    
        public Long getL2() {
            return L2;
        }
    
        public void setL2(Long l2) {
            L2 = l2;
        }
    
        public Double getD2() {
            return D2;
        }
    
        public void setD2(Double d2) {
            D2 = d2;
        }
    
        public Float getF2() {
            return F2;
        }
    
        public void setF2(Float f2) {
            F2 = f2;
        }
    
        public BigDecimal getBd() {
            return bd;
        }
    
        public void setBd(BigDecimal bd) {
            this.bd = bd;
        }
    
        public BigInteger getGi() {
            return gi;
        }
    
        public void setGi(BigInteger gi) {
            this.gi = gi;
        }
    
        public Number(Byte b2, Short s2, Integer i2, Long l2, Double d2, Float f2) {
            B2 = b2;
            S2 = s2;
            I2 = i2;
            L2 = l2;
            D2 = d2;
            F2 = f2;
        }
    
        @Override
        public String toString() {
            return "Number{" +
                    "b=" + b +
                    ", s=" + s +
                    ", i=" + i +
                    ", l=" + l +
                    ", d=" + d +
                    ", f=" + f +
                    ", B2=" + B2 +
                    ", S2=" + S2 +
                    ", I2=" + I2 +
                    ", L2=" + L2 +
                    ", D2=" + D2 +
                    ", F2=" + F2 +
                    ", bd=" + bd +
                    ", gi=" + gi +
                    '}';
        }
    }

    我们先来回顾一下,出现这种情况的具体使用场景。

    现在,有这样一种需求:

    要将json数组转变成List,Gson的实现语法如下:

    new Gson().fromJson(json, new TypeToken<List<T>>(){}.getType());

    以下三种调用方式,将会导致整数变小数:

    Number number = new Number((byte)1, (short)2, 3, 4L, 5D, 6F);
    List<Number> numbers = new ArrayList<>(1);
    numbers.add(number);
    String gsonStrs = new Gson().toJson(numbers);
    System.out.println(gsonStrs);
    // 错误方式一:不加泛型限制
    List<Number> numberList = new Gson().fromJson(gsonStrs, new TypeToken<List>(){}.getType());
    System.out.println(numberList);
    // 错误方式二:使用反射
    numberList = new Gson().fromJson(gsonStrs, new TypeToken<List<?>>(){}.getType());
    System.out.println(numberList);

     

    错误方式三:封装使用

    List<Number> numberList = JsonUtils.toJavaBeansByGson(gsonStrs);
    System.out.println(numberList);

    执行结果如下: 

    3.解决方案

    前两种错误实现方式,一般人不会犯这样的错误。

    问题在于第三种,有些让人猝不及防。

    本来,我想着是,对Gson再进行一次封装,这样下次直接调用即可,不用再写那么长的代码了,结果就是:

    弄巧成拙!

    我们加上具体的泛型限制,再来看一下执行结果。

    List<Number> numberList = new Gson().fromJson(gsonStrs, new TypeToken<List<Number>>(){}.getType());
    System.out.println(numberList);

     

    我们可以看到,这次是没有问题的。

    方式一:List必须使用具体的实体类进行限制;

    所以说,如果,想要使用通过gson将json数组转换成list实体类,list必须要指定具体的泛型类。

    换句话说就是,不能再对gson将json数组转成list的方式进行二次封装。

    如果像错误方式三那样封装使用的话,必须保证你的java实体类不包含数值类型属性,否则,将会全部转成小数Double类型。

    方式二:重新封装。

    既然上面那种方式不能再次进行封装,那我们不妨换一种思路:

    既然实现起来有bug,我们不用它不就行了?

    来,一起试试Gson将json字符串转java对象有没有问题:

    Number number = new Number((byte)1, (short)2, 3, 4L, 5D, 6F);
    String gsonStr = new Gson().toJson(number);
    System.out.println(gsonStr);
    
    Number numberGson = new Gson().fromJson(gsonStr, Number.class);
    System.out.println(numberGson.toString());

     

    我们可以看到,json字符串转java对象,通过gson转换,也是没有问题的。

    那么,我们就可以:将json数组字符串先转json数组,再对其进行遍历将其(json对象)转成java对象,塞到list当中。

    /*
     * JsonArray字符串转List(Gson)
     * @description:
     * @date: 2022/3/24 19:21
     * @param: jsons json数组字符串
     * @param: clazz 实体类
     * @return: java.util.List<T>
     */
    @Nullable
    public static <T> List<T> toJavaBeansByGson(String jsons, Class<T> clazz) {
        // net.sf.json
        JSONArray jsonArray = JSONArray.fromObject(jsons);
    
        if (arraysIsEmpty(jsonArray)) return null;
        
        List<T> beans = new ArrayList<>(jsonArray.size());
        jsonArray.forEach(netJson -> beans.add(new Gson().fromJson(netJson.toString(), clazz)));
        return beans;
    }

    测试

    Number number = new Number((byte)1, (short)2, 3, 4L, 5D, 6F);
    List<Number> numbers = new ArrayList<>(1);
    numbers.add(number);
    String gsonStrs = new Gson().toJson(numbers);
    System.out.println(gsonStrs);
    
    List<Number> numberList = JsonUtils.toJavaBeansByGson(gsonStrs, Number.class);
    System.out.println(numberList);

     

    我们可以看到,数值类型的转换是没有问题的。

    总结:

    当我们少量需要使用gson将字符串转list时,可以使用第一种方式;

    如果有大量位置需要用gson完成转换的话,可以考虑使用第二种实现方式。

    写在最后

      哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

     相关推荐:

  • 相关阅读:
    LUA脚本中的方法使用冒号和点,以及调用者使用冒号和点
    Lua类对象的继承
    Lua类对象和类对象的单例
    toLua使用protobuf协议转Lua表
    关于Lua表的弱引用
    Lua-面向对象中函数使用时冒号(:)和点(.)的区别
    Python【day 14-5】sorted filter map函数应用和练习
    Python【day 14-4】sorted filter map+递归文件夹+二分法查找
    Python【day 14-3】二分法查找
    Python【day 14-2】递归遍历文件夹
  • 原文地址:https://www.cnblogs.com/Marydon20170307/p/16054020.html
Copyright © 2020-2023  润新知