Android-Gson使用详解

Gson的基本用法
Gson解析默认使用方法很简单,将json转换成对象用Gson.fromJson(),将对象转化成json用Gson.toJson()即可。Gson解析解析数组和List也是用相同的方法。当解析List的时候,可能会遇到泛型操作。此时需要使用TypeToken对象来实现泛型支持。
public  static  void main( String[] args){
         Gson gson  =  new  Gson();

         //解析基础类型
         int i  = gson .fromJson( "100"int .class);               //100
         double d  = gson .fromJson( "\"99.99\""double .class);   //99.99
         boolean b  = gson .fromJson( "true"boolean .class);      // true
         String str  = gson .fromJson( "String"String .class);    // String
         String jsonNumber  = gson .toJson( 100f);        // 100
         String jsonBoolean  = gson .toJson( false);     // false
         String jsonString  = gson .toJson( "String");  //"String"

         //解析自定义类型
         User user  =  new  User( "怪盗kidou", 24);
         String jsonObject  = gson .toJson(user);  // {"name":"怪盗kidou","age":24}
         String jsonStringObj  =  "{\"name\":\"怪盗kidou\",\"age\":24}";
         User userObj  = gson .fromJson(jsonString,  User .class);

         //解析数组和List列表
         String json  =  "[\"Android\",\"Java\",\"PHP\"]";
         String[] strings  = gson .fromJson(json,  String[] .class);
         List stringList  = gson .fromJson(json,  new  TypeToken>() {} .getType());
    }

     public  static  class  User {
         public  String name;
         public  int age;

         public  User( String  nameint  age){
             this .name  = name;
             this .age  = age;
        }
    }

属性重命名 @SerializedName 注解
Gson通过@SerializedName 注解提供备选属性名,@SerializedName注解提供了两个属性,value和alternate。
  • alternate:接收一个String数组,数组中的String都为备选属性名
  • value:接收一个String对象,作为默认映射的json属性名。添加此属性,将导致java对象属性名的默认映射无效
public  static  void main( String[] args){
         Gson gson  =  new  Gson();
         String jsonString  =  "{\"name\":\"怪盗kidou\",\"age\":24,\"emailAddress\":\"[email protected]\"}";
         User userObj  = gson .fromJson(jsonString,  User .class);
        jsonString  =  "{\"name\":\"怪盗kidou\",\"age\":24,\"email_address\":\"[email protected]\"}";
        userObj  = gson .fromJson(jsonString,  User .class);
        jsonString  =  "{\"name\":\"怪盗kidou\",\"age\":24,\"email\":\"[email protected]\"}";
        userObj  = gson .fromJson(jsonString,  User .class);
    }

     public  static  class  User {
         @SerializedName( value  =  "emailAddress"alternate  = { "email""email_address"})
         public  String emailAddress;
         public  String name;
         public  int age;
    }

Gson支持泛型
Java中List 和List 在编译后,都是同一个类,即List.class,这是Java泛型使用时的泛型擦除。而Gson是使用反射来编译对象的 ,所以Gson要支持泛型转化,需要通过TypeToken类的帮助。泛型反序列化List需要通过以下方式:
Gson .fromJson(jsonArray,  new  TypeToken>() {} .getType());
使用示例如下:
public  static  void main( String arg[]){
         Gson gson  =  new  Gson();
         String json  =  "{\"code\":\"0\",\"message\":\"success\",\"data\":{\"name\":\"daiyibo\"\"age\":15}}";
         Result object  = gson .fromJson(json,  new  TypeToken>() {} .getType());
        json  =  "{\"code\":\"0\",\"message\":\"success\",\"data\":[{\"name\":\"daiyibo\"\"age\":15}, {\"name\":\"android\"\"age\":15}]}";
         Result> list  = gson .fromJson(json,  new  TypeToken>>() {} .getType());
         System .out .print(list .toString());
    }

     public  static  class  Result {
         public  int code;
         public  String message;
         public  T data;
    }

     public  static  class  User{
         public  String name;
         public  int age;
    }

流方式反序列化
流式反序列化,主要通过stream包下的JsonReader类来手动实现反序列化;流式序列化,主要通过stream包下JsonWriter类来实现序列化。
public static void main(String[] args) throws Exception{
        // 流式反序列化
        String json = "{\"name\":\"怪盗kidou\",\"age\":\"24\"}";
        User user = new User();
        JsonReader reader = new JsonReader(new StringReader(json));
        reader.beginObject(); // throws IOException
        while (reader.hasNext()) {
            String s = reader.nextName();
            switch (s) {
                case "name":
                    user.name = reader.nextString();
                    break;
                case "age":
                    user.age = reader.nextInt(); //自动转换
                    break;
                case "email":
                    user.email = reader.nextString();
                    break;
            }
        }
        reader.endObject();
        System.out.println(user);

        // 流式序列化
        JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
        writer.beginObject() // throws IOException
                .name("name").value("怪盗kidou")
                .name("age").value(24)
                .name("email").nullValue() //演示null
                .endObject(); // throws IOException
        writer.flush(); // throws IOException
        //{"name":"怪盗kidou","age":24,"email":null}
    }

    public static class User {
        public String email;
        public String name;
        public int age;
    }

GsonBuilder构造自定义Gson
一般情况下Gson类提供的 API已经能满足大部分的使用场景,但我们需要更多更特殊、更强大的功能时,就需要对Gson进行特殊设置。GsonBuilder用于构建Gson实例的构造器,要改变Gson默认的设置必须使用该类配置Gson。常用配置如下:
Gson gson = new GsonBuilder()
        //序列化null
        .serializeNulls()
        // 设置日期时间格式,另有2个重载方法
        // 在序列化和反序化时均生效
        .setDateFormat("yyyy-MM-dd")
        // 禁此序列化内部类
        .disableInnerClassSerialization()
        //生成不可执行的Json(多了 )]}' 这4个字符)
        .generateNonExecutableJson()
        //禁止转义html标签
        .disableHtmlEscaping()
        //格式化输出
        .setPrettyPrinting()
        .create();

序列化暴露属性@Expose注解
默认Gson对象,不对@Expose注解进行处理。所以在普通new Gson()对象中,@Expose注解无效。@Expose注解是用于处理暴露字段的,该注解必须和GsonBuilder配合使用。需要注意的是,属性中添加@Expose注解表示需要被序列化,否则默认为不对其进行序列化。
@Expose注解提供了两个属性,deserialize和serialize。
  • deserialize:true表示反序列化生效,false表示反序列化不生效,默认为true
  • serialize:true表示序列化生效,false表示序列化不生效,默认为true
public static void main(String[] args) throws Exception{

        Gson gson = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation()
                .create();
        User user = new User();
        user.name = "daiyibo";
        user.age = 15;
        gson.toJson(user);
    }

    public static class User {
        //等价于@Expose(deserialize = false,serialize = false)
        public int age;
        @Expose
        public String name;
    }

Gson控制版本
Gson在对基于版本的字段提供了两个注解 @Since 和 @Until,和GsonBuilder.setVersion(Double)配合使用。@Since 和 @Until都接收一个Double值。
  • @Since:当前版本(GsonBuilder中设置的版本)大于等于Since的值时该字段导出
  • @Until:当前版本(GsonBuilder中设置的版本)小于Until的值时该该字段导出
public static void main(String[] args) throws Exception{
        SinceUntilSample sinceUntilSample = new SinceUntilSample();
        sinceUntilSample.since = "since";
        sinceUntilSample.until = "until";
        Gson gson = new GsonBuilder().setVersion(5).create();
        System.out.println(gson.toJson(sinceUntilSample));
        //当version <4时,结果:{"until":"until"}
        //当version >=4 && version <5时,结果:{"since":"since","until":"until"}
        //当version >=5时,结果:{"since":"since"}
    }

    public static class SinceUntilSample {
        @Since(4)
        public String since;
        @Until(5)
        public String until;
    }

Gson控制访问修饰符
通过对类中的属性,修饰不同的修饰符,例如public、static 、final、private、protected。然后,使用GsonBuilder.excludeFieldsWithModifiers()构建gson,设置过滤的修饰符属性(java.lang.reflect.Modifier类中获取)
public static void main(String[] args) throws Exception{

        ModifierSample modifierSample = new ModifierSample();
        Gson gson = new GsonBuilder()
                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE)
                .create();
        System.out.println(gson.toJson(modifierSample));
        // 结果:{"publicField":"public","protectedField":"protected","defaultField":"default"}
    }

    public static class ModifierSample {
        final String finalField = "final";
        static String staticField = "static";
        public String publicField = "public";
        protected String protectedField = "protected";
        String defaultField = "default";
        private String privateField = "private";
    }

Gson基于策略过滤字段
通过设置GsonBuilder中的addSerializationExclusionStrategy()设置序列化和addDeserializationExclusionStrategy()设置反序化。这两个方法的参数为Gson的ExclusionStrategy接口,主要用于描述在序列化(反序列化)时,被过滤的字段和类。
ExclusionStrategy方法介绍
  • public boolean shouldSkipField(FieldAttributes f);//决定是否排除该字段,return true为排除
  •  public boolean shouldSkipClass(Class clazz);//是否排除类,return true为排除 
Gson gson = new GsonBuilder()
                .addSerializationExclusionStrategy(new ExclusionStrategy() {
                    @Override
                    public boolean shouldSkipField(FieldAttributes f) {
                        //这里作判断,决定要不要排除该字段,return true为排除
                        //按字段名排除
                        if ("finalField".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) {
                        // 直接排除某个类 ,return true为排除
                        return (clazz == int.class || clazz == Integer.class);
                    }
                })
                .create();

GsonBuilder属性重命名
直接通过GsonBuilder设置属性重命名,有两个方式setFieldNamingPolicy()和setFieldNamingStrategy()。setFieldNamingPolicy()相当于的setFieldNamingStrategy()方法的子集,并且Gson总结了经常使用的情况的枚举类FieldNamingPolicy。注意点:@SerializedName注解拥有最高优先级,在加有@SerializedName注解的字段上FieldNamingStrategy不生效!
setFieldNamingPolicy使用介绍
public static void main(String[] args) throws Exception{
        Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
                .create();

        String json = gson.toJson(new User());
        System.out.println(json);
    }

    public static class User {
        private String userinfo = "userinfo";
        private String userInfo = "userInfo";
    }
枚举类型作用介绍
 IDENTITY  {"emailAddress":"[email protected]"}
LOWER_CASE_WITH_DASHES   {"email-address":"[email protected]"}
 LOWER_CASE_WITH_UNDERSCORES  {"email_address":"[email protected]"}
 UPPER_CAMEL_CASE  {"EmailAddress":"[email protected]"}
UPPER_CAMEL_CASE_WITH_SPACES  {"Email Address":"[email protected]"} 
setFieldNamingStrategy使用介绍
public static void main(String[] args) throws Exception{
        Gson gson = new GsonBuilder()
                .setFieldNamingStrategy(new FieldNamingStrategy() {
                    @Override
                    public String translateName(Field f) {
                        //实现自己的规则
                        if ("userInfo".equals(f.getName())){
                            return "u_s_e_r_i_n_f_o";
                        }
                        return f.getName();
                    }
                })
                .create();
        String json = gson.toJson(new User());
        System.out.println(json);
    }

    public static class User {
        private String userInfo = "userInfo";
    }

TypeAdapter,JsonSerializer,JsonDeserializer介绍
TypeAdapter,JsonSerializer,JsonDeserializer三个类的简单描述
  • TypeAdapter,抽象类形式,主要用来接管某种类型的序列化和反序列化过程,主要包含两个方法write(JsonWriter,T) 和 read(JsonReader)
  • JsonSerializer,为接口形式,主要用来接管序列化的过程
  • JsonDeserializer,为接口形式,主要用来接管反序列化的过程
Gson.registerTypeAdapter()与Gson.registerTypeHierarchyAdapter()两个方法来注册TypeAdapter,JsonSerializer,JsonDeserializer适配单元。
  • Gson.registerTypeAdapter(),主要用来注册类,不支持继承。即,注册Number.class时,Integer.class也不生效。
  • Gson.registerTypeHierarchyAdapter(),主要用来注册类,支持继承。即,注册Number.class时,Integer.class也生效。
public static void main(String[] args) throws Exception {
        User user = new User();
        user.name = "怪盗kidou";
        user.age = 24;
        user.email = "[email protected]";
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(User.class, new UserTypeAdapter())//为User注册TypeAdapter
                .create();
        // 序列化
        String json = gson.toJson(user);
        System.out.println(json);//out: {"name":"怪盗kidou","age":24,"email":"[email protected]"}
        // 反序列化
        json = "{\"name\":\"怪盗kidou\",\"age\":24,\"email\":\"[email protected]\"}";
        user = gson.fromJson(json, User.class);
        System.out.println(user);//out: name:怪盗kidou age:24 email:[email protected]
        json = "{\"name\":\"怪盗kidou\",\"age\":24,\"email_address\":\"[email protected]\"}";
        user = gson.fromJson(json, User.class);
        System.out.println(user);//out: name:怪盗kidou age:24 email:[email protected]
        json = "{\"name\":\"怪盗kidou\",\"age\":24,\"emailAddress\":\"[email protected]\"}";
        user = gson.fromJson(json, User.class);
        System.out.println(user);//out: name:怪盗kidou age:24 email:[email protected]

        // JsonDeserializer与JsonSerializer使用介绍
        gson = new GsonBuilder()
                .registerTypeAdapter(Integer.class, new IntegerJsonDeserializer())
                .registerTypeAdapter(Integer.class, new IntegerJsonSerializer())
                .create();
        System.out.println(gson.toJson(100));//out: "number:100"
        System.out.println(gson.fromJson("\"\"", Integer.class));//out: -1
    }

    public static class UserTypeAdapter extends TypeAdapter<User> {

        @Override
        public void write(JsonWriter out, User value) throws IOException {
            out.beginObject();
            out.name("name").value(value.name);
            out.name("age").value(value.age);
            out.name("email").value(value.email);
            out.endObject();
        }

        @Override
        public User read(JsonReader in) throws IOException {
            User user = new User();
            in.beginObject();
            while (in.hasNext()) {
                switch (in.nextName()) {
                    case "name":
                        user.name = in.nextString();
                        break;
                    case "age":
                        user.age = in.nextInt();
                        break;
                    case "email":
                    case "email_address":
                    case "emailAddress":
                        user.email = in.nextString();
                        break;
                }
            }
            in.endObject();
            return user;
        }
    }

    public static class IntegerJsonDeserializer implements JsonDeserializer<java.lang.Integer> {
        public java.lang.Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                            throws JsonParseException {
            try {
                return json.getAsInt();
            } catch (NumberFormatException e) {
                return -1;
            }
        }
    }

    public static class IntegerJsonSerializer implements JsonSerializer<java.lang.Integer> {
        public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context){
            return new JsonPrimitive("number:" + String.valueOf(src));
        }
    }

    public static class User{
        private String name;
        private int age;
        private String email;

        public String toString(){
            return "name:" + name + " age:" + age + " email:" + email;
        }
    }

TypeAdapterFactory
TypeAdapterFactory用于创建TypeAdapter的工厂类,通过对比Type,确定有没有对应的TypeAdapter,没有就返回null,与GsonBuilder.registerTypeAdapterFactory配合使用。使用示范如下:
public static void main(String[] args) throws Exception {
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new TypeAdapterFactory() {
                    @Override
                    public  TypeAdapter create(Gson gson, TypeToken type) {
                        if (type.equals(new TypeToken() {}.getType())){
                            return (TypeAdapter) new UserTypeAdapter();
                        }
                        return null;
                    }
                })
                .create();
        // 序列化
        User user = new User();
        user.name = "daiyibo";
        user.age = 24;
        user.email = "[email protected]";
        System.out.println(gson.toJson(user));//out: {"name":"daiyibo","age":24,"email":"[email protected]"}
        user = gson.fromJson("{\"name\":\"daiyibo\",\"age\":24,\"email_address\":\"[email protected]\"}", User.class);
        System.out.println(user.toString());//out: {"name":"daiyibo","age":24,"email":"[email protected]"}
    }

    public static class UserTypeAdapter extends TypeAdapter<User> {

        @Override
        public void write(JsonWriter out, User value) throws IOException {
            out.beginObject();
            out.name("name").value(value.name);
            out.name("age").value(value.age);
            out.name("email").value(value.email);
            out.endObject();
        }

        @Override
        public User read(JsonReader in) throws IOException {
            User user = new User();
            in.beginObject();
            while (in.hasNext()) {
                switch (in.nextName()) {
                    case "name":
                        user.name = in.nextString();
                        break;
                    case "age":
                        user.age = in.nextInt();
                        break;
                    case "email":
                    case "email_address":
                    case "emailAddress":
                        user.email = in.nextString();
                        break;
                }
            }
            in.endObject();
            return user;
        }
    }

    public static class User{
        private String name;
        private int age;
        private String email;

        public String toString(){
            return "name:" + name + " age:" + age + " email:" + email;
        }
    }

@JsonAdapter注解
@JsonAdapter是用在类上的注解,接收一个参数,且必须是TypeAdpater,JsonSerializer或JsonDeserializer这三个其中之一,用来定义该类的序列化方法。注意点:@JsonAdapter的优先级比GsonBuilder.registerTypeAdapter的优先级更高。使用方法如下:
public static void main(String[] args) throws Exception {
        Gson gson = new Gson();
        User user = new User();
        user.name = "daiyibo";
        user.age = 24;
        user.email = "[email protected]";
        System.out.println(gson.toJson(user));//out: {"name":"daiyibo","age":24,"email":"[email protected]"}
        user = gson.fromJson("{\"name\":\"daiyibo\",\"age\":24,\"email_address\":\"[email protected]\"}", User.class);
        System.out.println(user.toString());//out: {"name":"daiyibo","age":24,"email":"[email protected]"}
    }

    @JsonAdapter(UserTypeAdapter.class)
    public static class User{
        private String name;
        private int age;
        private String email;

        public String toString(){
            return "name:" + name + " age:" + age + " email:" + email;
        }
    }

    public static class UserTypeAdapter extends TypeAdapter<User> {

        @Override
        public void write(JsonWriter out, User value) throws IOException {
            out.beginObject();
            out.name("name").value(value.name);
            out.name("age").value(value.age);
            out.name("email").value(value.email);
            out.endObject();
        }

        @Override
        public User read(JsonReader in) throws IOException {
            User user = new User();
            in.beginObject();
            while (in.hasNext()) {
                switch (in.nextName()) {
                    case "name":
                        user.name = in.nextString();
                        break;
                    case "age":
                        user.age = in.nextInt();
                        break;
                    case "email":
                    case "email_address":
                    case "emailAddress":
                        user.email = in.nextString();
                        break;
                }
            }
            in.endObject();
            return user;
        }
    }

Gson源码UML类图
Android-Gson使用详解_第1张图片

Gson解析流程图
Android-Gson使用详解_第2张图片

Gson如何解决泛型问题
Gson反序列化泛型时,使用如下方式:
Type collectionType = new TypeToken>(){}.getType();
Collection ints2 = gson.fromJson(json, collectionType);
这里生成了TypeToken的匿名类来实现泛型标记,在TypeToken构造函数中,会生成type对象(getType()返回值)。type实际赋值语句如下:
//实际内容:com.google.gson.reflect.TypeToken>
Type superclass = subclass.getGenericSuperclass();
//实际内容:MainTest.MainTest$Result
return ((ParameterizedType) superclass).getActualTypeArguments()[0];


参考
官方文档:
https://github.com/google/gson/blob/master/UserGuide.md#TOC-Future-Enhancements-to-Gson
Gson源码分析:
http://blog.csdn.net/chunqiuwei/article/details/49338053
http://blog.csdn.net/chunqiuwei/article/details/49535419
泛型类型擦除参考:
http://www.importnew.com/13907.html

你可能感兴趣的:(java,Android)