美文网首页
Java基础-序列化/反序列化-gson基础知识

Java基础-序列化/反序列化-gson基础知识

作者: 程序猿老徐 | 来源:发表于2022-04-09 00:57 被阅读0次

    以下内容来之官网翻译,地址

    1.Gson依赖

    1.1.Gradle/Android

    dependencies {
        implementation 'com.google.code.gson:gson:2.9.0'
    }
    

    1.2.maven

    <dependencies>
        <!--  Gson: Java to Json conversion -->
        <dependency>
          <groupId>com.google.code.gson</groupId>
          <artifactId>gson</artifactId>
          <version>2.9.0</version>
          <scope>compile</scope>
        </dependency>
    </dependencies>
    

    1.2.Gson简单实用

    1.2.1.基础类型

    // Serialization
    Gson gson = new Gson();
    gson.toJson(1);            // ==> 1
    gson.toJson("abcd");       // ==> "abcd"
    gson.toJson(new Long(10)); // ==> 10
    int[] values = { 1 };
    gson.toJson(values);       // ==> [1]
    
    // Deserialization
    int one = gson.fromJson("1", int.class);
    Integer one = gson.fromJson("1", Integer.class);
    Long one = gson.fromJson("1", Long.class);
    Boolean false = gson.fromJson("false", Boolean.class);
    String str = gson.fromJson("\"abc\"", String.class);
    String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);
    

    1.2.2.对象

    class BagOfPrimitives {
      private int value1 = 1;
      private String value2 = "abc";
      private transient int value3 = 3;
      BagOfPrimitives() {
        // no-args constructor
      }
    }
    
    // Serialization
    BagOfPrimitives obj = new BagOfPrimitives();
    Gson gson = new Gson();
    String json = gson.toJson(obj);  
    
    // ==> json is {"value1":1,"value2":"abc"}
    
    // Deserialization
    BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
    // ==> obj2 is just like obj
    

    Notes 如果对象内存在循环引用,序列化时将导致死循环。

    例如:

    
    @Data
    public class RecursionObject {
    
        private String name;
    
        private RecursionReferObject refer;
    }
    
    
    @Data
    public class RecursionReferObject {
    
        private String name;
    
        private RecursionObject refer;
    }
    
    
    
    public class GsonRecursionTest {
    
    
        public static void main(String[] args) {
            RecursionObject parent = new RecursionObject();
            parent.setName("1");
    
            RecursionReferObject son = new RecursionReferObject();
            son.setName("2");
    
            parent.setRefer(son);
            son.setRefer(parent);
            
            Gson gson = new GsonBuilder().create();
            String json=gson.toJson(parent);
            System.out.println(json);
            RecursionObject recursionObject=gson.fromJson(json,RecursionObject.class);
            System.out.println(recursionObject);
        }
    }
    
    
    /***
    Exception in thread "main" java.lang.StackOverflowError
        at com.google.gson.stream.JsonWriter.string(JsonWriter.java:566)
        at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:402)
        at com.google.gson.stream.JsonWriter.value(JsonWriter.java:417)
        at com.google.gson.internal.bind.TypeAdapters$16.write(TypeAdapters.java:406)
        at com.google.gson.internal.bind.TypeAdapters$16.write(TypeAdapters.java:390)
    /**
    
    

    说明:

    • 推荐对象字段使用基础类型
    • 不需要添加给字段添加注解来表示该字段需要序列化,因为当前类(所有父类)中的所有字段默认都会被序列化
    • 如果一个字段被标记为transient,默认它在序列化/反序列化时会被忽略
    • null的处理
      • 当序列化时,一个null字段会被省略
      • 当反序列化时,如果一个字段找不到,则对应的对象字段会被设置为以下默认值:对象类型为null,数值类型为0,boolean类型为false
    • 被synthetic 标记的字段,也会在序列化/反序列化过程中被忽略
    • 内部类、匿名类、本地类所对应的外部类字段,在序列化/反序列化过程中也将会忽略(这块没太理解)

    1.2.3.内部类(没看太懂)

    Gson can serialize static nested classes quite easily.

    Gson can also deserialize static nested classes. However, Gson can not automatically deserialize the pure inner classes since their no-args constructor also need a reference to the containing Object which is not available at the time of deserialization. You can address this problem by either making the inner class static or by providing a custom InstanceCreator for it. Here is an example:

    public class A { 
      public String a; 
    
      class B { 
    
        public String b; 
    
        public B() {
          // No args constructor for B
        }
      } 
    }
    

    NOTE: The above class B can not (by default) be serialized with Gson.

    Gson can not deserialize {"b":"abc"} into an instance of B since the class B is an inner class. If it was defined as static class B then Gson would have been able to deserialize the string. Another solution is to write a custom instance creator for B.

    public class InstanceCreatorForB implements InstanceCreator<A.B> {
      private final A a;
      public InstanceCreatorForB(A a)  {
        this.a = a;
      }
      public A.B createInstance(Type type) {
        return a.new B();
      }
    }
    

    The above is possible, but not recommended.

    1.2.4.Array

    Gson gson = new Gson();
    int[] ints = {1, 2, 3, 4, 5};
    String[] strings = {"abc", "def", "ghi"};
    
    // Serialization
    gson.toJson(ints);     // ==> [1,2,3,4,5]
    gson.toJson(strings);  // ==> ["abc", "def", "ghi"]
    
    // Deserialization
    int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class); 
    // ==> ints2 will be same as ints
    

    支持多维。

    1.2.5.集合

    Gson gson = new Gson();
    Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);
    
    // Serialization
    String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]
    
    // Deserialization
    Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
    Collection<Integer> ints2 = gson.fromJson(json, collectionType);
    // ==> ints2 is same as ints
    

    限制:gson可以序列化任意对象的集合,但是反序列化时需要指定集合元素的类型。

    1.2.泛型

    1.2.1.TypeToken的使用

    1.2.1.1.对象类型的泛型
    class Foo<T> {
      T value;
    }
    Gson gson = new Gson();
    Foo<Bar> foo = new Foo<Bar>();
    gson.toJson(foo); // May not serialize foo.value correctly
    
    gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
    
    Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
    gson.toJson(foo, fooType);
    gson.fromJson(json, fooType);
    

    通过TypeToken来定义泛型类型。

    1.2.1.2.集合类型的泛型
    
    @Data
    public class Bar {
    
        private String name;
    }
    
    public class GsonListTest {
    
        public static void main(String[] args) {
            Gson gson = new GsonBuilder().create();
    
            List<Bar> bars = new ArrayList<>();
    
            Bar bar = new Bar();
            bar.setName("bar 1");
    
            bars.add(bar);
            String json = gson.toJson(bars);
            System.out.println(json);
            Type type = new TypeToken<List<Bar>>(){}.getType();
            List<Bar> dbars = gson.fromJson(json,type);
            System.out.println(dbars);
    
        }
    }
    
    /**
    [{"name":"bar 1"}]
    [Bar(name=bar 1)]
    ***/
    
    

    1.2.2.自定义ParameterizedType

    在实际项目中,如果使用大量使用TypeToken,定义起来会比较麻烦,查看TypeToken的底层源码,发现它也是通过ParameterizedType来实现的。(不懂ParameterizedType的可以先百度一下)

    
    public class MyParameterizedType implements ParameterizedType {
    
        private Type[] args;
    
        private Class rawType;
    
        public MyParameterizedType( Class rawType,Type[] args) {
            this.args = args;
            this.rawType = rawType;
        }
    
        @Override
        public Type[] getActualTypeArguments() {
            return args;
        }
    
        @Override
        public Type getRawType() {
            return rawType;
        }
    
        @Override
        public Type getOwnerType() {
            return null;
        }
    }
    
    
    //测试复杂泛型类型
    
    public class ParameterizedTypeTest {
    
        public static void main(String[] args) {
            Gson gson = new GsonBuilder().create();
            Result<List<Bar>> result = new Result<>();
            List<Bar> bars = new ArrayList<>();
            Bar bar = new Bar();
            bar.setName("bar 1");
            bars.add(bar);
            result.setData(bars);
          
            Type inner = new MyParameterizedType(List.class, new Class[]{Bar.class});
            MyParameterizedType type = new MyParameterizedType(Result.class,new Type[]{inner});
          
            String json = gson.toJson(result);
            System.out.println(json);
            Result<List<Bar>> result1=gson.fromJson(json,type);
            System.out.println(result1);
    
        }
    }
    
    

    1.3.null值处理

    Gson gson = new GsonBuilder().serializeNulls().create();
    
    
    
    public class Foo {
      private final String s;
      private final int i;
    
      public Foo() {
        this(null, 5);
      }
    
      public Foo(String s, int i) {
        this.s = s;
        this.i = i;
      }
    }
    
    Gson gson = new GsonBuilder().serializeNulls().create();
    Foo foo = new Foo();
    String json = gson.toJson(foo);
    System.out.println(json);
    
    json = gson.toJson(null);
    System.out.println(json);
    
    {"s":null,"i":5}
    null
    
    

    相关文章

      网友评论

          本文标题:Java基础-序列化/反序列化-gson基础知识

          本文链接:https://www.haomeiwen.com/subject/frwusrtx.html