Gson解析

来源:互联网 发布:阿里云 香港节点 速度 编辑:程序博客网 时间:2024/06/02 05:30

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

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

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


Gson的实例化方式:

1: Gson gson new Gson();

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

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


阅读全文

原创粉丝点击