1.Gson使用

1.1 tojson && fromjson 序列化和反序列

基本属性 primitives
// 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);
类-Object
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

注意:

1.推荐类中属性使用私有属性。

2.序列化和反序列化不需要注解,所有都使用默认的。

3.transient 属性不被序列化和反序列

4.如何处理空值

5.synthetic属性不被序列化和反序列化

6.内部类中对应外部类的属性将被忽略,不会被序列化和反序列化

7.匿名类和内部类会被排除。经验证匿名类仍然会被序列化,但内部类会被排除

Array && Collections
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
Gson gson = new Gson();
Collection<Integer> ints = Arrays.asList(1,2,3,4,5);

// Serialization
String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]

// Deserialization
TypeToken<Collection<Integer>> collectionType = new TypeToken<Collection<Integer>>(){};
// Note: For older Gson versions it is necessary to use `collectionType.getType()` as argument below,
// this is however not type-safe and care must be taken to specify the correct type for the local variable
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints

注意:Collection 在反序列化时,需要使用泛型TypeToken,因为它无法指定结果类的具体类型

Map
Gson gson = new Gson();
Map<String, String> stringMap = new LinkedHashMap<>();
stringMap.put("key", "value");
stringMap.put(null, "null-entry");

// Serialization
String json = gson.toJson(stringMap); // ==> json is {"key":"value","null":"null-entry"}

Map<Integer, Integer> intMap = new LinkedHashMap<>();
intMap.put(2, 4);
intMap.put(3, 6);

// Serialization
String json = gson.toJson(intMap); // ==> json is {"2":4,"3":6}

// Deserialization
Gson gson = new Gson();
TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){};
String json = "{"key": "value"}";

// Note: For older Gson versions it is necessary to use `mapType.getType()` as argument below,
// this is however not type-safe and care must be taken to specify the correct type for the local variable
Map<String, String> stringMap = gson.fromJson(json, mapType);
// ==> stringMap is {key=value}

注意:Gson默认java.util.Map使用Json对象的形式序列化,本质上是在Map上调用toString()方法

​ 但对于复杂的Map对象需要使用这个功能GsonBuilder().enableComplexMapKeySerialization(),如果使用了这个功能,将会使用TypeAdapter#write()方法代替toString()

class PersonName {
  String firstName;
  String lastName;

  PersonName(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  // ... equals and hashCode
}

Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
Map<PersonName, Integer> complexMap = new LinkedHashMap<>();
complexMap.put(new PersonName("John", "Doe"), 30);
complexMap.put(new PersonName("Jane", "Doe"), 35);

// Serialization; complex map is serialized as a JSON array containing key-value pairs (as JSON arrays)
String json = gson.toJson(complexMap);
// ==> json is [[{"firstName":"John","lastName":"Doe"},30],[{"firstName":"Jane","lastName":"Doe"},35]]
//
//若具备Enable的gson对象序列化常规的Map类型,还是会序列化成常规的Json对象
Map<String, String> stringMap = new LinkedHashMap<>();
stringMap.put("key", "value");
// Serialization; non-complex map is serialized as a regular JSON object
String json = gson.toJson(stringMap); // json is {"key":"value"}

若使用不具备Enable的gson对象,会导致编码的键格式错误如下:

Gson gson = new Gson();
String json = gson.toJson(complexMap);
// ==> {"com.example.androiddemo.gson.PersonName@8e33f51":30,"com.example.androiddemo.gson.PersonName@fb2d3b6":35}
泛型

泛型无法直接使用toJson()||fromJson(),因为获取的class类型是 泛型的class,因此需要使用TypeTokenClass

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);

问题为什么使用new TypeToken<Foo<Bar>>() {}匿名内部类来获取getType(),直接使用new () 不好吗?

:Java5之后规定了新的Class文件格式规范方法与域的描述符增添了对泛型信息记录。因此泛型写到Class文件有这样的一个规律:

因此出现这样的情况:

List<String> list1 = new ArrayList<String>();//左侧声明 右侧使用
List list2 = new ArrayList<String>();//左侧声明 右侧使用

实例1 list1class文件中会保存String这个传入的泛型参数信息(路径),而实例2list2没有包含String。

同理,

new TypeToken<Foo<Bar>>()//若只是用new(),则相当于TypeToken<T> = new TypeToken<Foo<Bar>>() 和实例2一样
new TypeToken<Foo<Bar>>(){} //使用匿名内部类相当于TypeToken<Foo<Bar>> = new TypeToken<Foo<Bar>>() 和实例1一样

这样就不会出现找不到正确的泛型类型问题

RowType就是类型擦除后的原始类型

除了类型擦除这个原因之外,TypeToken使用匿名内部类的原因,是因为TypeToken无参构造函数作用域protected。

使用匿名内部类的场景

复杂类型集合

像以下复杂类型集合,无法直接使用TypeToken实现反序列化。

Collection collection = new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS", "guest"));
class Event {
  private String name;
  private String source;
  private Event(String name, String source) {
    this.name = name;
    this.source = source;
  }
}
String json = gson.toJson(collection); //toJson可以直接使用。

因此,gson提供了以下几种方案:

1.2 GsonBuilder的其他属性

主要是指序列化时的影响

1.3 自定义序列化和反序列化

Gson为常用的类内置了一些序列化和反序列化,参考TypeAdapters

但是提供的内置方法往往不够使用,因此提供了以下的方法自定义序列化和反序列化。

GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(MyType2.class, new MyTypeAdapter());
gson.registerTypeAdapter(MyType.class, new MySerializer());
gson.registerTypeAdapter(MyType.class, new MyDeserializer());
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());

registerTypeAdapter提供了检查是否至少实现了一种以上的接口并且注册他们。

JSON Serializers

实现JsonSerializer接口,借助JsonElement实现对特定的需求进行序列化,由源码可知最后调用serialize()方法。

//设置boolean类型为0 或1
public class BooleanSerializer implements JsonSerializer<Boolean> {

	public JsonElement serialize(Boolean aBoolean, Type type,
		JsonSerializationContext jsonSerializationContext) 
	{
		if(aBoolean){
		   return new JsonPrimitive(1);
		}
		return new JsonPrimitive(0);
	}
}
public static void main(String[] args) throws Exception 
	{
		Employee emp = new Employee(1, "Lokesh", "Gupta", "howtodoinjava@gmail.com", true);

		Gson gson = new GsonBuilder()
				.registerTypeAdapter(Boolean.class, new BooleanSerializer())
				.setPrettyPrinting()
				.create();

		String json = gson.toJson(emp);

		System.out.println(json);
	}
JSON Deserializers

同理,实现JsonDeserializers接口,借助JsonElement实现

//将年月日转换成LocalData
public class Employee 
{
	private Integer id;
    private String firstName;
    private String lastName;
    private String email;
    private LocalDate dob;
}
public class EmployeeDeserializer implements JsonDeserializer<Employee> 
{  
    @Override
    public Employee deserialize(JsonElement json, Type typeOfT, 
    			JsonDeserializationContext context) throws JsonParseException 
    {
        JsonObject jsonObject = json.getAsJsonObject();

        LocalDate localDate = LocalDate.of(
                jsonObject.get("year").getAsInt(),
                jsonObject.get("month").getAsInt(),
                jsonObject.get("day").getAsInt()
        );

        return new Employee(
        		jsonObject.get("id").getAsInt(), 
        		jsonObject.get("firstName").getAsString(), 
        		jsonObject.get("lastName").getAsString(), 
        		jsonObject.get("email").getAsString(), 
        		localDate);
    }
}
//注册使用即可
Instance Creators

可使用场景

1.需要重新定义行为创建方式。如创建子类

2.创建的实例也是泛型的,通过ParameterizedType获取Type类型

//第二种情况
public class Id<T> {
  private final Class<T> classOfId;
  private final long value;
  public Id(Class<T> classOfId, long value) {
    this.classOfId = classOfId;
    this.value = value;
  }
}
class IdInstanceCreator implements InstanceCreator<Id<?>> {
  public Id<?> createInstance(Type type) {
    Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
    Type idType = typeParameters[0]; // Id has only one parameterized type T
    return new Id((Class)idType, 0L);
  }
}
//使用
Gson gson=new GsonBuilder()
  .registerTypeAdapter(Id.getClass(),new IdInstanceCreator())
  .create();
String json="";
Id<Foo> id=gson.fromJson(json,Id.getClass());

InstanceCreater源码解析

知晓其何时创建实例,学习gson优秀的源码

1.InstanceCreater注册

private final Map<Type, InstanceCreator<?>> instanceCreators
  = new HashMap<Type, InstanceCreator<?>>();

//先放在map中
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {

  if (typeAdapter instanceof InstanceCreator<?>) {
    //放入map中
    instanceCreators.put(type, (InstanceCreator) typeAdapter);
  }
  //省略部分代码
  return this;
}

 public Gson create() {

    addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);

    //删除本文无关的代码
    return new Gson(...,..., instanceCreators,
        ..., ...,
        ..., ..., ..., ...,
        ..., ..., ...);
  }
//Gson构造函数
 private final ConstructorConstructor constructorConstructor;
 Gson(。。。,
      final Map<Type, InstanceCreator<?>> instanceCreators, 。。。。。) {
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);

从中可以看出最后instanceCreators以map的形式放在Gson对象中持有的ConstructorConstructor对象中的map中。

//Gson持有ConstructorConstructor对象。
public final class ConstructorConstructor {
  private final Map<Type, InstanceCreator<?>> instanceCreators;

  public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) {
    this.instanceCreators = instanceCreators;
  }

ReflectiveTypeAdapterFactory对象初始化TypeAdapter时,会获取ObjectConstruct。

//Gson初始化时会将ConstructorConstructor对象传递给ReflectiveTypeAdapterFactory
Gson(,,,,,,,){
  factories.add(new ReflectiveTypeAdapterFactory(
        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
}
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
    //根据type获取ObjectConstructor
    ObjectConstructor<T> constructor = constructorConstructor.get(type);
    return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
  }

然后看一下,ObjectConstructor#get方法来实现获取Type对应的实例,为什么要加一个ConstructorConstructor来获取实例。

public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
    final Type type = typeToken.getType();
    final Class<? super T> rawType = typeToken.getRawType();

    // 创建对象方式A
    final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
    //客户端没有传InstanceCreator的时候为null
    if (typeCreator != null) {
      return new ObjectConstructor<T>() {//省略部分代码 };
    }

    // 创建对象方式B
    final InstanceCreator<T> rawTypeCreator =
        (InstanceCreator<T>) instanceCreators.get(rawType);
     //客户端没有传InstanceCreator的时候为null   
    if (rawTypeCreator != null) {
      return new ObjectConstructor<T>() {
        @Override public T construct() {//省略部分代码 }
      };
    }

   // 创建对象方式C
    //如果没有配置InstanceCreator的实现
    ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
    if (defaultConstructor != null) {
      return defaultConstructor;
    }

 // 创建对象方式D

//如果没有配置InstanceCreator的实现
 ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
    if (defaultImplementation != null) {
      return defaultImplementation;
    }

    // finally try unsafe
    return newUnsafeAllocator(type, rawType);
  }

此处使用了设计模式——策略模式,有五种策略来实现获取对象实例。

1、根据type通过客户端传入的InstanceCreator
2、根据rawType通过客户端传入的InstanceCreator
3、通过constructor 的newInstance 详见newDefaultConstructor方法
4、判断是否是集合对象,来初始化目标javaBean对象,详见newDefaultImplementationConstructor
5、最后调用newUnsafeAllocator来完成对象的初始,详见newUnsafeAllocator。

2.使用入口:创建对象的实例,在Adapter中(ReflectiveTypeAdapterFactory)来创建实例

 //创建对象的实例:这段至关重要 参考《Gson反射解析机制详解(1)》
public T read(JsonReader in) throws IOException {
      //....
      //实例化一个对象  constructor是ObjectConstructor<T>
      T instance = constructor.construct();

        in.beginObject();
        //遍历json为instance的字段自动赋值
        while (in.hasNext()) {
          String name = in.nextName();
          BoundField field = boundFields.get(name);
          if (field == null || !field.deserialized) {
            in.skipValue();
          } else {
            field.read(in, instance);
          }
        }

      in.endObject();
      //返回一个java bean对象
      return instance;
    }

从而在Gson的constructor#construct 获取实例。

 T instance = constructor.construct(); 
TypeAdapter实现自定义序列化和反序列化

TypeAdapter和Serializer、Deserializer起到相同的作用,区别在于TypeAdapter使用流来解析数据,而不是使用JsonElement.

GsonBuilder().registerTypeAdapter()可知,TypeAdapter会以工厂模式方式添加到factories。

public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
    Objects.requireNonNull(type);
    $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
        || typeAdapter instanceof JsonDeserializer<?>
        || typeAdapter instanceof InstanceCreator<?>
        || typeAdapter instanceof TypeAdapter<?>);
    ...
    if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
      TypeToken<?> typeToken = TypeToken.get(type);
      //Serializer、Deserializer 封装在了TreeTypeAdapter中
      factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
    }
    if (typeAdapter instanceof TypeAdapter<?>) {
      //这里新建了Factory
      @SuppressWarnings({"unchecked", "rawtypes"})
      TypeAdapterFactory factory = TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter);
      factories.add(factory);
    }
    return this;
  }

主要使用了read()write()方法来实现对Json数据流处理,以下是一个demo.

public class BookTypeAdapter extends TypeAdapter {
 
  @Override
  public Book read(final JsonReader in) throws IOException {
    final Book book = new Book();
 
    in.beginObject();
    while (in.hasNext()) {
      switch (in.nextName()) {
      case "isbn":
        book.setIsbn(in.nextString());
        break;
      case "title":
        book.setTitle(in.nextString());
        break;
      case "authors":
        book.setAuthors(in.nextString().split(";"));
        break;
      }
    }
    in.endObject();
 
    return book;
  }
 
  @Override
  public void write(final JsonWriter out, final Book book) throws IOException {
    out.beginObject();
    out.name("isbn").value(book.getIsbn());
    out.name("title").value(book.getTitle());
    out.name("authors").value(StringUtils.join(book.getAuthors(), ";"));
    out.endObject();
  }
}

1.4 常用的类

Object

每个类包括数组都继承自Object

Class

Class是一个类。类对象由Java虚拟机自动构建用于表示JVM运行时类或接口信息。Class类的构造函数设计私有的,这意味着我们不能通过new的方式来创建Class对象,只有JVM才能创建该类的实例。

Type

是一个接口,自1.5之后,是Java所有类型的通用超级接口

Raw Type:原始类型,包括类和接口基本数据类型和不涉及泛型的所有引用类型(类、接口数组)均是Class类型。

Parameterized types:参数化类型,指泛型,例如List是一个参数化类型。

  • getActualTypeArguments()返回Type[],即“<>”里的参数比如Map<String,Integer>
  • getRawType()返回Tpye,得到“<>”前面的类型,比如List
  • getOwnerType()返回Type,返回ParameterizedType类型所在的类的Type。如Map.Entry<String,Object>这个参数化类型返回的是Map(因为Map.Entry这个类型所在的类是Map)的类型。

Array types:带有泛型的数组类型,也就是带有参数化类或者接口所表示的数组对应的类型,例如 List s[]、Map<String,Integer> map[]等对应的类型均是GenericArrayType类型,而List s[]、Map map[]是Class类型。

类型变量(type variables):也叫泛型变量,即泛型中的变量,例如:T、K、V等变量,可以表示任何类。
基本数据类型(primitive types):byte、shortboolean、char、int、long、floatdouble八大基本数据类型
通配符类型(WildcardType) :通配符对应的类型,例如 List<? extends Object> 中?对应的类型

原文地址:https://blog.csdn.net/qq_32035241/article/details/129567270

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_15339.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注