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

博客 动态
0 232
优雅殿下
优雅殿下 2022-04-09 10:57:43
悬赏:0 积分 收藏

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

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

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.基础类型

// SerializationGson gson = new Gson();gson.toJson(1);            // ==> 1gson.toJson("abcd");       // ==> "abcd"gson.toJson(new Long(10)); // ==> 10int[] values = { 1 };gson.toJson(values);       // ==> [1]// Deserializationint 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  }}// SerializationBagOfPrimitives obj = new BagOfPrimitives();Gson gson = new Gson();String json = gson.toJson(obj);  // ==> json is {"value1":1,"value2":"abc"}// DeserializationBagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);// ==> obj2 is just like obj

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

例如:

@Datapublic class RecursionObject {    private String name;    private RecursionReferObject refer;}@Datapublic 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"};// Serializationgson.toJson(ints);     // ==> [1,2,3,4,5]gson.toJson(strings);  // ==> ["abc", "def", "ghi"]// Deserializationint[] 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);// SerializationString json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]// DeserializationType 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 correctlygson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as BarType fooType = new TypeToken<Foo<Bar>>() {}.getType();gson.toJson(foo, fooType);gson.fromJson(json, fooType);

通过TypeToken来定义泛型类型。

1.2.1.2.集合类型的泛型
@Datapublic 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
posted @ 2022-04-09 10:53 程序员老徐 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2018 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员