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