Gson(http://www.jianshu.com/p/e740196225a4) Gson解决的问题 Gson处理对象的几个重要点

  • Serialization:序列化,使Java对象到Json字符串的过程。
  • Deserialization:反序列化,字符串转换成Java对象。
  1. 提供一种像toString()和构造方法的很简单的机制,来实现Java 对象和Json之间的互相转换。

  2. 允许已经存在的无法改变的对象,转换成Json,或者Json转换成已存在的对象。

  3. 允许自定义对象的表现形式

  4. 支持任意的复杂对象

  5. 能够生成可压缩和可读的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(
 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的属性也进行序列化