- Serialization:序列化,使Java对象到Json字符串的过程。
- Deserialization:反序列化,字符串转换成Java对象。
Gson解决的问题
- 提供一种像toString()和构造方法的很简单的机制,来实现Java 对象和Json之间的互相转换。
- 允许已经存在的无法改变的对象,转换成Json,或者Json转换成已存在的对象。
- 允许自定义对象的表现形式
- 支持任意的复杂对象
- 能够生成可压缩和可读的Json的字符串输出。
Gson处理对象的几个重要点
1 推荐把成员变量都声明称private的
2 没有必要用注解(@Expose 注解)指明某个字段是否会被序列化或者反序列化,所有包含在当前类(包括父类)中的字段都应该默认被序列化或者反序列化
3 如果某个字段被 transient 这个Java关键词修饰,就不会被序列化或者反序列化
4 下面的实现方式能够正确的处理null
1)当序列化的时候,如果对象的某个字段为null,是不会输出到Json字符串中的。
2)当反序列化的时候,某个字段在Json字符串中找不到对应的值,就会被赋值为null
5 如果一个字段是 synthetic
的,他会被忽视,也即是不应该被序列化或者反序列化
6 内部类(或者anonymous class(匿名类),或者local class(局部类,可以理解为在方法内部声明的类))的某个字段和外部类的某个字段一样的话,就会被忽视,不会被序列化或者反序列化
Gson的基本用法
int i = gson.fromJson("100", int.class); String jsonNumber = gson.toJson(100); User user = new User("怪盗kidou",24); String jsonObject = gson.toJson(user); String jsonString = "{\"name\":\"怪盗kidou\",\"age\":24}"; User user = gson.fromJson(jsonString, User.class);
@SerializedName 注解重命名属性
使用这个注解注释的属性,在json中,将会使用新的名字来进行对应
注解有两个参数 value——对于序列化和反序列化都好使 alternate——只有反序列化好使
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"}) public String emailAddress;
比如说,客户端传回来一张图片,不管参数是img、imgine,我都能通过alternate参数来影射成POJO类中的对应的那个参数,非常的方便。
Gson中使用泛型
如果要处理数组类型非常的简单:
Gson gson = new Gson(); String jsonArray = "[‘Android‘,‘Java‘,‘PHP‘]"; String[] strings = gson.fromJson(jsonArray, String[].class);
但是像要处理集合类就比较困难了,因为直接使用List<String>.class 得到的就是List的类,并不能知道里面的泛型的类型
对于Java来说List<String>
和List<User>
这俩个的字节码文件只一个那就是List.class
,这是Java泛型使用时要注意的问题 泛型擦除。
这里就需要使用TypeToken来进行处理了
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
GsonBuilder
一般情况下Gson
类提供的 API已经能满足大部分的使用场景,但我们需要更多更特殊、更强大的功能时,这时候就引入一个新的类 GsonBuilder,这个类用于配置Gson的默认配置。
GsonBuilder用法
Gson gson = new GsonBuilder() //各种配置 .create(); //生成配置好的Gson
实际上是产生了Gson的实例,但是在中间增加了一些配置,只要的配置有:
1,Gson在默认情况下,是不会序列化值为null的键的。
Gson gson = new GsonBuilder().serializeNulls().create(); //这样就会序列化值为null的键了
2,其他的配置
Gson gson = new GsonBuilder() //序列化null .serializeNulls() // 设置日期时间格式,另有2个重载方法 // 在序列化和反序化时均生效 .setDateFormat("yyyy-MM-dd") // 禁此序列化内部类 .disableInnerClassSerialization() //生成不可执行的Json(多了 )]}‘ 这4个字符) .generateNonExecutableJson() //禁止转义html标签 .disableHtmlEscaping() //格式化输出 .setPrettyPrinting() .create();
字段过滤的几种方法
1,@Expose注解
注解作用在属性上,有两个参数值 deserialize和serialize,默认为true,如果设置为false,那么对应的字段就不会被序列化/反序列化
这里实例化Gson的时候需要使用GsonBuilder
Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create(); gson.toJson(category);
2,@Since
和 @Until注解
基于版本号,只有在某些版本上,字段才有效,使用GsonBuilder来进行版本的监控
new GsonBuilder().setVersion(1.2).create();
3,基于访问修饰符
这个跟基于@Expose的很类似,只是排除了特定修饰符的方法。
Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE) .create();
4,基于策略,使用自定义的规则
//通过一个内部类,完成了自定义的字段的筛选,这里是指定了反序列化的规则,还可以使用序列化函数指定序列化的规则
Gson g2=new GsonBuilder().addDeserializationExclusionStrategy(
new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { //返回true的就是要排除的,这里是根据字段来排除 if ("name".equals(f.getName())) return true; //按字段名排除 Expose expose = f.getAnnotation(Expose.class); if (expose != null && expose.deserialize() == false) return true; //按注解排除 return false; } @Override public boolean shouldSkipClass(Class<?> clazz) { //返回true的就是要排除的,这里是根据字段的类来排除 if(clazz.equals(int.class)) //直接排除了int型的属性 return true; return false; } }).create();
一些简单的例子:
Gson ggg=new GsonBuilder().setDateFormat("yyyy-mm-dd").serializeNulls().create();
设置了时间的格式,并且要求对于null的属性也进行序列化