Gson 解析教程

来源:互联网 发布:java file.getlength 编辑:程序博客网 时间:2024/05/22 17:37

Gson 是google解析Json的一个开源框架,同类的框架fastJson,JackJson等等

本人fastJson用了两年,也是从去年才开始接触Gson,希望下面的总结会对博友有用,至于Gson与FastJson的对比,其实半斤八两的问题,不再赘述

第一步:在AS下面创建java工程 并添加gson依赖

compile 'com.google.code.gson:gson:2.6.2'



Gson的实例化方式:

1:Gson gson=newGson();

2:通过GsonBuilder 可以配置多种选项

 gson = new GsonBuilder()                    .setLenient()// json宽松                    .enableComplexMapKeySerialization()//支持Map的key为复杂对象的形式                    .serializeNulls() //智能null                    .setPrettyPrinting()// 调教格式                    .disableHtmlEscaping() //默认是GSON把HTML 转义的                    .create();
Gson的基本用法:

 JavaBean转换Json字符串

 gson提供 publicString toJson(Object src) 方法可以将对象转换成jsonStr

  

package com.xuan.gson;import com.google.gson.Gson;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 10:39 */public class GsonTest1 {    public static class Student {        private String name;        private int age;        //省略setter getter equals    }    private static void log(String msg) {        System.out.println(msg);    }    public static void main(String[] args) throws Exception {        Gson gson = new Gson();        Student student = new Student();        student.setName("xuanyouwu");        student.setAge(26);        String jsonStr = gson.toJson(student);        log("---->javabean convert jsonStr:" + jsonStr);    }}

运行结果:

---->javabean convert jsonStr:{"name":"xuanyouwu","age":26}




    List Map转Json字符串

package com.xuan.gson;import com.google.gson.Gson;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 10:39 */public class GsonTest1 {    private static void log(String msg) {        System.out.println(msg);    }    public static void main(String[] args) throws Exception {        Gson gson = new Gson();        List<String> list = Arrays.asList("1", "a", "3", "rt", "5");        log("---->list convert jsonStr:" + gson.toJson(list));        Map<String, Object> content = new HashMap<String, Object>();        content.put("name", "xuanyouwu");        content.put("age", "26");        log("---->map convert jsonStr:" + gson.toJson(content));    }}
运行结果:
---->list convert jsonStr:["1","a","3","rt","5"]---->map convert jsonStr:{"name":"xuanyouwu","age":"26"}

       Json字符串转JavaBean

        String studentJsonStr="{\"name\":\"xuanyouwu\",\"age\":26}";        Student student1 = gson.fromJson(studentJsonStr, Student.class);        log("------->json convert JavaBean:"+student1);

      运行结果:

            ------->json convert JavaBean:Student{name='xuanyouwu', age=26}



   Json字符串转List

        String listJsonStr="[\"1\",\"a\",\"3\",\"rt\",\"5\"]";
        Type type = new TypeToken<ArrayList<String>>() {        }.getType();        ArrayList<String> sList=gson.fromJson(listJsonStr, type);        log("------->json convert List:"+sList);
    运行结果:
        ------->json convert List:[1, a, 3, rt, 5]
</pre><pre code_snippet_id="1687762" snippet_file_name="blog_20160518_11_939636" name="code" class="java">  Gson封装的类型体系
    Gson里面有一个非常有意思的抽象基类JsonElement,他的继承体系:
    <img src="http://img.blog.csdn.net/20160518135136864?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
 JsonObject等同于org的JSONObject,JsonArray也类似,
   JsonNull 其实就是null 字段
     JsonNull jsonNull=new JsonNull();//构造方法过时,推荐INSTANCE

      JsonNull jsonNull=JsonNull.INSTANCE;        log("-----"+jsonNull);
   运行结果:
      -----null

     JsonPrimitive非常有意思,我们知道如果json转换成字符串 可能包含引号的转义,但是通过JsonPrimative我们可以获得为转义的字符串,看实例:

     

package com.xuan.gson;import com.google.gson.JsonNull;import com.google.gson.JsonPrimitive;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest2 {    private static void log(String msg) {        System.out.println(msg);    }    public static void main(String[] args) throws Exception {        String studentJsonStr="{\"name\":\"xuanyouwu\",\"age\":26}";        log("------>studentJsonStr:"+studentJsonStr);        JsonPrimitive jsonPrimitive=new JsonPrimitive(studentJsonStr);        log("------>jsonPrimitive:"+jsonPrimitive);        log("------>jsonPrimitive:"+jsonPrimitive.toString());        log("------>jsonPrimitive:"+jsonPrimitive.getAsString());        JsonPrimitive jsonPrimitive2=new JsonPrimitive("this is String");        log("------>jsonPrimitive2:"+jsonPrimitive2);        log("------>jsonPrimitive2:"+jsonPrimitive2.toString());        log("------>jsonPrimitive2:"+jsonPrimitive2.getAsString());    }}

     运行结果:

------>studentJsonStr:{"name":"xuanyouwu","age":26}
------>jsonPrimitive:"{\"name\":\"xuanyouwu\",\"age\":26}"
------>jsonPrimitive:"{\"name\":\"xuanyouwu\",\"age\":26}"
------>jsonPrimitive:{"name":"xuanyouwu","age":26}
------>jsonPrimitive2:"this is String"
------>jsonPrimitive2:"this is String"
------>jsonPrimitive2:this is String




       创建JsonObject

           通过addPropert(key,value)可以向jsonObject中添加字段 跟hashMap类似

        JsonObject jsonObject=new JsonObject();        jsonObject.addProperty("name","xuanyouwu");        jsonObject.addProperty("age",26);        log("------>create jsonObject:"+jsonObject);
            运行结果:

                ------>create jsonObject:{"name":"xuanyouwu","age":26}



    创建JsonArray       

     JsonArray jsonElements=new JsonArray();        jsonElements.add("a");        jsonElements.add("b");        jsonElements.add("c");        jsonElements.add("d");        log("------>create jsonArray:"+jsonElements);
          运行结果:

          ------>create jsonArray:["a","b","c","d"]



     JsonObject 嵌套数组或者说嵌套JsonArray

           通过JsonObject的add(key,JsonElement)可以为jsonObject 添加一个数组的字段

        JsonObject jsonObject2=new JsonObject();        jsonObject2.addProperty("name","xuanyouwu");        jsonObject2.addProperty("age",26);        JsonArray jsonElements2=new JsonArray();        jsonElements2.add("骑车");        jsonElements2.add("打游戏");        jsonElements2.add("看电视");        jsonObject2.add("hobby",jsonElements2);        log("------>create jsonObject inner JsonArray:"+jsonObject2);
           运行结果:

            ------>create jsonObject inner JsonArray:{"name":"xuanyouwu","age":26,"hobby":["骑车","打游戏","看电视"]}




Gson注解

          在Gson中有五类注解

          




          重命名注解:SerializedName 

             作用:转换关键字key,json转换成JavaBean时,json字段的key 默认必须和我们声明类的字段名称一样,当服务器端返回了关键字怎么办,比如key 为new switch这样,我们    在声明类的时候不能写这样的字段,可能你想服务器端改动,他可能要改数据库,但是我告诉你,做服务端的大部分不愿意改动他的json,是很自私的!这时候重命名注解都排上用场了   第二种场景:服务器端返回的json 的key 简直太丑,或者太长,你想简化,my_parent_name,可以简化成mpn 比较优雅简介

          实例:

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.annotations.SerializedName;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest3 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        public int age;        @SerializedName("new")        public int isnew;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    ", isnew=" + isnew +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\n" +                "    \"age\": 26,\n" +                "    \"name\": \"zhangsan\",\n" +                "    \"new\": 1\n" +                "}";        Gson gson = new Gson();        User user = gson.fromJson(jsonFromServer, User.class);        log("------>user:" + user);    }}

运行结果: ------>user:User{name='zhangsan', age=26, isnew=1}


package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.annotations.SerializedName;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest3 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User2 {        public String name;        public int age;        @SerializedName("my_parent_name")        public String pn;        @Override        public String toString() {            return "User2{" +                    "name='" + name + '\'' +                    ", age=" + age +                    ", pn='" + pn + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer2="{\n" +                "    \"age\": 26,\n" +                "    \"my_parent_name\": \"zhangsanf\",\n" +                "    \"name\": \"zhangsan\"\n" +                "}";        Gson gson2 = new Gson();        User2 user2 = gson2.fromJson(jsonFromServer2, User2.class);        log("------>user2:" + user2);    }}

运行结果: ------>user2:User2{name='zhangsan', age=26, pn='zhangsanf'}


        作用2:结合alternate 提供多种备用字段key来解析,@SerializedName(value ="desc",alternate = {"other","note"})  如果json中有other就会解析成desc 如果有note也会解析成desc,注意1:value中的值不能出现在alternate中,注意2:alternate的备选字段 会后面的替换前面的

   实例:

   

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.annotations.SerializedName;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest4 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        public int age;        @SerializedName(value = "desc",alternate = {"other","note"})        public String desc;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    ", desc='" + desc + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\n" +                "    \"age\": 26,\n" +                "    \"other\": \"成都人\",\n" +                "    \"name\": \"zhangsan\"\n" +                "}";        Gson gson = new Gson();        User user = gson.fromJson(jsonFromServer, User.class);        log("------>user:" + user);        String jsonFromServer2 = "{\n" +                "    \"age\": 26,\n" +                "    \"note\": \"成都人\",\n" +                "    \"name\": \"zhangsan\"\n" +                "}";        User user2 = gson.fromJson(jsonFromServer2, User.class);        log("------>user:" + user2);        //包括desc 与note note在desc之后        String jsonFromServer3="{\n" +                "    \"age\": 26,\n" +                "    \"desc\": \"desc成都人\",\n" +                "    \"name\": \"zhangsan\",\n" +                "    \"note\": \"note成都人\"\n" +                "}";        User user3 = gson.fromJson(jsonFromServer3, User.class);        log("------>user:" + user3);        //包括desc 与note note在desc之前        String jsonFromServer4="{\n" +                "    \"age\": 26,\n" +                "    \"note\": \"note成都人\",\n" +                "    \"name\": \"zhangsan\",\n" +                "    \"desc\": \"desc成都人\"\n" +                "}";        User user4 = gson.fromJson(jsonFromServer4, User.class);        log("------>user:" + user4);    }}
  运行结果:

     ------>user:User{name='zhangsan', age=26, desc='成都人'}
------>user:User{name='zhangsan', age=26, desc='成都人'}
------>user:User{name='zhangsan', age=26, desc='note成都人'}
------>user:User{name='zhangsan', age=26, desc='desc成都人'}



  Gson @Expose过滤注解 

  源码:默认既可以序列化又可以反序列化

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface Expose {    public boolean serialize() default true;  public boolean deserialize() default true;}
</pre><pre code_snippet_id="1687762" snippet_file_name="blog_20160518_25_4965554" name="code" class="java">可以排除不需要序列化的字段,需要配合GsonBuilder使用
<pre style="font-family: 宋体; font-size: 9pt; background-color: rgb(255, 255, 255);"><pre name="code" class="java"> Gson gson = new GsonBuilder()                .excludeFieldsWithoutExposeAnnotation()                .create();

  不添加@Expose注解的字段将不会解析:
   分为以下几种情况:
    1:不添加@Expose注解等同于@Expose(deserialize = false,serialize = false) 不做任何解析
    2:@Expose(deserialize = true,serialize = false) 只解析用用,也就是反序列化可以,序列化不可以
    3:@Expose(deserialize = false,serialize = true) 序列化可以,反序列化不行
    4:@Expose(deserialize = true,serialize = true) 既可以序列化,也可以反序列化
    实例:将分别演示这四种情况
  不添加@Expose注解:等同于@Expose(deserialize = false,serialize = false)
package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest5 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\"name\": \"zhangsan\"}";        Gson gson = new GsonBuilder()                .excludeFieldsWithoutExposeAnnotation()                .create();        User user = gson.fromJson(jsonFromServer, User.class);        log("------>反序列化:" + user);        User user1 = new User();        user1.name = "zhangsan2";        String userStr = gson.toJson(user1);        log("------>序列化:" + userStr);    }}

运行结果:
------>反序列化:User{name='null'}------>序列化:{}
  添加@Expose注解 
package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.annotations.Expose;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest5 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        @Expose //等同于 @Expose(deserialize = true,serialize = true)        public String name;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\"name\": \"zhangsan\"}";        Gson gson = new GsonBuilder()                .excludeFieldsWithoutExposeAnnotation()                .create();        User user = gson.fromJson(jsonFromServer, User.class);        log("------>反序列化:" + user);        User user1 = new User();        user1.name = "zhangsan2";        String userStr = gson.toJson(user1);        log("------>序列化:" + userStr);    }}

运行结果:

------>反序列化:User{name='zhangsan'}
------>序列化:{"name":"zhangsan2"}



@Expose注解 只序列化

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.annotations.Expose;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest5 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        @Expose(deserialize = false,serialize = true)        public String name;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\"name\": \"zhangsan\"}";        Gson gson = new GsonBuilder()                .excludeFieldsWithoutExposeAnnotation()                .create();        User user = gson.fromJson(jsonFromServer, User.class);        log("------>反序列化:" + user);        User user1 = new User();        user1.name = "zhangsan2";        String userStr = gson.toJson(user1);        log("------>序列化:" + userStr);    }}

运行结果:

------>反序列化:User{name='null'}------>序列化:{"name":"zhangsan2"}

      @Expose 只反序列化

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.annotations.Expose;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest5 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        @Expose(deserialize = true, serialize = false)        public String name;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\"name\": \"zhangsan\"}";        Gson gson = new GsonBuilder()                .excludeFieldsWithoutExposeAnnotation()                .create();        User user = gson.fromJson(jsonFromServer, User.class);        log("------>反序列化:" + user);        User user1 = new User();        user1.name = "zhangsan2";        String userStr = gson.toJson(user1);        log("------>序列化:" + userStr);    }}

运行结果:

 ------>反序列化:User{name='zhangsan'}
------>序列化:{}



    @Since(float v)注解  版本控制 

      结合GsonBuilder.setVersion(n)使用 当n>=v时 才会序列化解析

 

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.annotations.Since;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest6 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        @Since(2)        public String name;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\"name\": \"zhangsan\"}";        Gson gson = new GsonBuilder()                .setVersion(1)//版本为1                .create();        User user1 = gson.fromJson(jsonFromServer, User.class);        log("------>反序列化v=1:" + user1);        User user1_1 = new User();        user1_1.name = "zhangsan2";        String userStr = gson.toJson(user1_1);        log("------>序列化v=1:" + userStr);        Gson gson2 = new GsonBuilder()                .setVersion(2)//版本为2                .create();        User user2 = gson2.fromJson(jsonFromServer, User.class);        log("------>反序列化v=2:" + user2);        User user2_1 = new User();        user2_1.name = "zhangsan2";        String userStr2_1 = gson2.toJson(user2_1);        log("------>序列化v=2:" + userStr2_1);        Gson gson3 = new GsonBuilder()                .setVersion(3)//版本为3                .create();        User user3 = gson3.fromJson(jsonFromServer, User.class);        log("------>反序列化v=3:" + user3);        User user3_1 = new User();        user3_1.name = "zhangsan2";        String userStr3_1 = gson3.toJson(user3_1);        log("------>序列化v=3:" + userStr3_1);    }}

运行结果:

------>反序列化v=1:User{name='null'}
------>序列化v=1:{}
------>反序列化v=2:User{name='zhangsan'}
------>序列化v=2:{"name":"zhangsan2"}
------>反序列化v=3:User{name='zhangsan'}
------>序列化v=3:{"name":"zhangsan2"}



    @Util(float v)注解 版本控制

      当gson的setVersion(n) n<v 才解析

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.annotations.Until;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest6 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        @Until(2)        public String name;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) throws Exception {        String jsonFromServer = "{\"name\": \"zhangsan\"}";        Gson gson = new GsonBuilder()                .setVersion(1)//版本为1                .create();        User user1 = gson.fromJson(jsonFromServer, User.class);        log("------>反序列化v=1:" + user1);        User user1_1 = new User();        user1_1.name = "zhangsan2";        String userStr = gson.toJson(user1_1);        log("------>序列化v=1:" + userStr);        Gson gson2 = new GsonBuilder()                .setVersion(2)//版本为2                .create();        User user2 = gson2.fromJson(jsonFromServer, User.class);        log("------>反序列化v=2:" + user2);        User user2_1 = new User();        user2_1.name = "zhangsan2";        String userStr2_1 = gson2.toJson(user2_1);        log("------>序列化v=2:" + userStr2_1);        Gson gson3 = new GsonBuilder()                .setVersion(3)//版本为3                .create();        User user3 = gson3.fromJson(jsonFromServer, User.class);        log("------>反序列化v=3:" + user3);        User user3_1 = new User();        user3_1.name = "zhangsan2";        String userStr3_1 = gson3.toJson(user3_1);        log("------>序列化v=3:" + userStr3_1);    }}

运行结果:

------>反序列化v=1:User{name='zhangsan'}
------>序列化v=1:{"name":"zhangsan2"}
------>反序列化v=2:User{name='null'}
------>序列化v=2:{}
------>反序列化v=3:User{name='null'}
------>序列化v=3:{}


Gson 高级用法

    相信看过retrofit2.0 源码的同学都知道,其中有一个GsonConverterFactory 里面的用法十分精炼老成,这里来一段源码

 



   据说使用TypeAdapter 效率更高,本人还未对比测试,暂时放后吧,TypeAdapter是什么玩意呢?

   在源码中备注了一句 Converts Java objects to and from JSON 就是对象json之间的互相转换 接替了T 泛型类的序列化和反序列化的逻辑

   从源码中我们看到区分了2.1版本之前后之后的用法,2.1版本之前可以自定义adapter:

   

public class PointAdapter extends TypeAdapter<Point> { *     public Point read(JsonReader reader) throws IOException { *       if (reader.peek() == JsonToken.NULL) { *         reader.nextNull(); *         return null; *       } *       String xy = reader.nextString(); *       String[] parts = xy.split(","); *       int x = Integer.parseInt(parts[0]); *       int y = Integer.parseInt(parts[1]); *       return new Point(x, y); *     } *     public void write(JsonWriter writer, Point value) throws IOException { *       if (value == null) { *         writer.nullValue(); *         return; *       } *       String xy = value.getX() + "," + value.getY(); *       writer.value(xy); *     } *   }}

    使用

  

GsonBuilder builder = new GsonBuilder(); *   builder.registerTypeAdapter(Point.class, new PointAdapter()); *   // if PointAdapter didn't check for nulls in its read/write methods, you should instead use *   // builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe()); *   ... *   Gson gson = builder.create();

    在2.1版本之后更推荐直接插入泛型就使用

//   String json = "{'origin':'0,0','points':['1,2','3,4']}";//   TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);//   Graph graph = graphAdapter.fromJson(json);// }</pre>// And an example for serialization: <pre>   {@code////   Graph graph = new Graph(...);//   TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);//   String json = graphAdapter.toJson(graph);// }</pre>

   实例:使用TypeAdapter 来序列化和反序列化
   
package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.TypeAdapter;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest7 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        public int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }    public static void main(String[] args) throws Exception {        Gson gson = new Gson();        TypeAdapter<User> userTypeAdapter = gson.getAdapter(User.class);        User user = new User();        user.name = "xuanyouwu";        user.age = 26;        String userJsonStr = userTypeAdapter.toJson(user);        log("------>序列化:" + userJsonStr);        User user1 = userTypeAdapter.fromJson(userJsonStr);        log("------>反序列化:" + user1);    }}
运行结果:
------>序列化:{"name":"xuanyouwu","age":26}------>反序列化:User{name='xuanyouwu', age=26}

Gson的容错机制:
   为什么要容错了,在javaBean中声明了int类型的age 如果服务端 返回的是"" 空字符串怎么办呢?崩溃?
   如果json格式不规范如 {name=zhangsan,age:26,hobby=null}  发现不是普通的key value
  容错实现方式1:
  1:创建Gson的方式
  gson = new GsonBuilder()                    .setLenient()// json宽松                    .create();
2:使用JsonReader
   JsonReader jsonReader = gson.newJsonReader(value.charStream());
   jsonReader.<span style="font-family: 宋体; font-size: 9pt;">setLenient(true)</span>

    3:自定义TypeAdapter

    4:使用注解JsonAdapter,其实也是自定义Adapter

 

 1.2归为一类 由框架实现,基本json大格式规范,键值对不标准,多引号的问题等等,而不报错停止解析,但是功能相对较弱

 能解决bug 

com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON 

3,4归为一类,都属于自定义adapter,但是3与gson绑定,4使用注解和字段绑定

 实例:

   

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.JsonParseException;import com.google.gson.TypeAdapter;import com.google.gson.stream.JsonReader;import com.google.gson.stream.JsonWriter;import java.io.IOException;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest8 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        public int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }        ;    }    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.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":                        try {                            String str = in.nextString();                            user.age = Integer.valueOf(str);                        } catch (Exception e) {                        }                        break;                }            }            in.endObject();            return user;        }    }    public static void main(String[] args) throws Exception {        Gson gson = new Gson();        String jsonStrFromServer = "{\n" +                "    \"age\": \"\",\n" +                "    \"name\": \"zhangsan\"\n" +                "}";        log("------->jsonFromServer:"+jsonStrFromServer);        try {            User user = gson.fromJson(jsonStrFromServer, User.class);            log("------>默认Gson 解析:" + user);        } catch (JsonParseException e) {//java.lang.NumberFormatException: empty String            log("------>默认Gson 解析 异常:" + e);        }        Gson gson2 = new GsonBuilder()                .registerTypeAdapter(User.class, new UserTypeAdapter()).create();        try {            User user2 = gson2.fromJson(jsonStrFromServer, User.class);            log("------>自定义adapter 解析:" + user2);        } catch (JsonParseException e) {//java.lang.NumberFormatException: empty String            log("------>自定义adapter 异常:" + e);        }        try {            UserTypeAdapter userTypeAdapter = new UserTypeAdapter();            User user3 = userTypeAdapter.fromJson(jsonStrFromServer);            log("------>自定义adapter 解析2:" + user3);        } catch (Exception e) {            log("------>自定义adapter 异常2:" + e);        }    }}

运行结果:

------->jsonFromServer:{
    "age": "",
    "name": "zhangsan"
}
------>默认Gson 解析 异常:com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String
------>自定义adapter 解析:User{name='zhangsan', age=0}
------>自定义adapter 解析2:User{name='zhangsan', age=0}

可以看到 age是空字符串 但是不影响整体的解析流程,这对客户端是十分友好的


  基于注解的方式,上面的方式倾向于整体,注解的方式倾向于字段

  

package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.JsonParseException;import com.google.gson.TypeAdapter;import com.google.gson.annotations.JsonAdapter;import com.google.gson.stream.JsonReader;import com.google.gson.stream.JsonWriter;import java.io.IOException;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest9 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        @JsonAdapter(IntegerTypeAdapter.class)        public int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }    public static class IntegerTypeAdapter extends TypeAdapter<Integer> {        @Override        public void write(JsonWriter out, Integer value) throws IOException {            out.value(value);        }        @Override        public Integer read(JsonReader in) throws IOException {            int i = 0;            try {                String str = in.nextString();                i = Integer.valueOf(str);            } catch (Exception e) {            }            return i;        }    }    public static class User2 {        public String name;        public int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }    public static void main(String[] args) throws Exception {        Gson gson = new Gson();        String jsonStrFromServer = "{\n" +                "    \"age\": \"\",\n" +                "    \"name\": \"zhangsan\"\n" +                "}";        log("------->jsonFromServer:" + jsonStrFromServer);        try {            User2 user2 = gson.fromJson(jsonStrFromServer, User2.class);            log("------>gson 解析:" + user2);        } catch (Exception e) {            log("------>gson 解析异常:" + e);        }        try {            User user = gson.fromJson(jsonStrFromServer, User.class);            log("------>JsonAdapter 注解 解析:" + user);        } catch (JsonParseException e) {//java.lang.NumberFormatException: empty String            log("------>JsonAdapter 注解 异常:" + e);        }    }}

运行结果:

------->jsonFromServer:{    "age": "",    "name": "zhangsan"}------>gson 解析异常:com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String------>JsonAdapter 注解 解析:User{name='zhangsan', age=0}
可以看到我们成功地跳过服务端返回json不合理的坑了吧
</pre><pre code_snippet_id="1687762" snippet_file_name="blog_20160519_47_1535429" name="code" class="java">不得不吐槽啊,像这种服务器端错误,应该完全归结服务端json不合理返回,
往往老板都会找客户端原因,怎么又崩溃了?怎么又不显示了?老板不会关心是不是数据返回不合理的问题的!
做客户端需要相当的承受能力哈,同意的点个赞哈
</pre><p>其实上面的方式保险是很保险,但是需要维护的地方多,代码量大,我们介绍另外一种方式:JsonSerializer与JsonDeserializer 之关系单方面的处理,可以全局注册某个类型的处理:看实例:</p><p><pre name="code" class="java">package com.xuan.gson;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.JsonDeserializationContext;import com.google.gson.JsonDeserializer;import com.google.gson.JsonElement;import com.google.gson.JsonParseException;import java.lang.reflect.Type;/** * @author xuanyouwu * @email xuanyouwu@163.com * @time 2016-05-18 11:20 */public class GsonTest10 {    private static void log(String msg) {        System.out.println(msg);    }    public static class User {        public String name;        public int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }    public static void main(String[] args) throws Exception {        JsonDeserializer<Integer> jsonDeserializer = new JsonDeserializer<Integer>() {            @Override            public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {                try {                    return json.getAsInt();                } catch (NumberFormatException e) {                    return 0;                }            }        };        Gson gson = new GsonBuilder()                .registerTypeAdapter(int.class, jsonDeserializer)                .create();        String jsonStrFromServer = "{\n" +                "    \"age\": \"\",\n" +                "    \"name\": \"zhangsan\"\n" +                "}";        log("------->jsonFromServer:" + jsonStrFromServer);        try {            User user = gson.fromJson(jsonStrFromServer, User.class);            log("------>  JsonDeserializer<Integer> 解析:" + user);        } catch (Exception e) {            log("------>  JsonDeserializer<Integer> 解析异常:" + e);        }        Gson gson1=new Gson();        try {            User user1 = gson1.fromJson(jsonStrFromServer, User.class);            log("------> 默认gson 解析:" + user1);        } catch (Exception e) {            log("------>  默认gson 解析异常:" + e);        }    }}
运行结果:

------->jsonFromServer:{
    "age": "",
    "name": "zhangsan"
}
------>  JsonDeserializer<Integer> 解析:User{name='zhangsan', age=0}
------>  默认gson 解析异常:com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String

 这样定义全局的反序列化工具就能避免解析异常


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕晚期挺着大肚子好累怎么办 古墓丽影崛起东西满了怎么办 塞尔达传说大师剑耐久没了怎么办 冒险岛遇见超能力者全屏挂机怎么办 当危险来临时该怎么办作文400字 生气把孩子手掌内侧打肿了怎么办 驾驶证未满一年扣12分怎么办 在高速上超速百分之10以下怎么办 中兴手机重启死机开不了机怎么办 太胖了太自卑了该怎么办 儿子因为长的胖特别自卑怎么办? 苹果ld叫我检查身份信息怎么办 我家墙让对面给漂水了怎么办 如果你流落到荒岛上你会怎么办 手机迅雷下载版权方不给下载怎么办 白色有彩色花纹的衣服染色了怎么办 载兰花假如下雪和打霜怎么办 皇室战争你的队友离开了对战怎么办 海岛奇兵发现求救信号第三个怎么办 海岛奇兵勋章太多对手太强怎么办 鱼为什么换缸鱼翅黑了怎么办 鱼丸捕鱼大作战换手机了怎么办 2o岁j'j小怎么办 为什么小米5s指纹不能用怎么办 cs录屏软件运行内存太大了怎么办 可是没有他我怎么办啊是什么电视剧 可是没有他我怎么办啊是哪个电视剧 手机太卡了打字打不了了怎么办 梦幻西游的将军令没有电了怎么办 将军令全部的序列号都忘记了怎么办 船员证被公司压着想自己换证怎么办 电子录入系统中无法打开影像怎么办 火车票退票后说银行退款失败怎么办 苹果4s玩游戏闪退怎么办 买了二手房原房主不迁户口怎么办 苹果禁反忘记工id密码了怎么办 玩英雄联盟用腾讯游戏平台卡怎么办 游戏代练接单了没有给我账号怎么办 华为手机进入设置立即闪退怎么办 股东发现公司有做假账现象怎么办 中国在服役期间有纹身被发现怎么办