Gson 解析教程
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="https://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<span style="font-family:'宋体';font-size:9pt;background-color:rgb(228,228,255);"> </span>
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
这样定义全局的反序列化工具就能避免解析异常
Gson 解析教程的更多相关文章
- 使用Gson解析json
前边的博客说过将json解析成java的方法,使用的是 这几个jar包,但是在解析时层遇到一个问题,就是在将时间字符串转换为java的Timestamp对象时会抛出异常,这个问题一直放在哪里没有去解决 ...
- 大话JSON之Gson解析JSON
(三)解析Json数组(多条Json数据) 比如有如下Json数据: [{'name':'John', 'grade':[{'course':'English','score':100},{'cour ...
- Android中使用Gson解析JSON数据的两种方法
Json是一种类似于XML的通用数据交换格式,具有比XML更高的传输效率;本文将介绍两种方法解析JSON数据,需要的朋友可以参考下 Json是一种类似于XML的通用数据交换格式,具有比XML更高的 ...
- Gson解析复杂的json数据
最近在给公司做一个直播APK的项目,主要就是通过解析网络服务器上的json数据,然后将频道地址下载下来再调用Android的播放器进行播放,原先本来打算使用普通的json解析方法即JsonObject ...
- 【框架】网络请求+Gson解析--Retrofit 2
其实内部是封装了Okhttp和Gson解析 public class CourseFragmentAPI { public static void get(String userId, BaseCal ...
- Gson解析数组多类型元素
本文的出现是为了解决以下需求:使用Gson对json数组进行解析,但是数组里面元素的类型是多种的.数据如下: {"list":[{ "type":0, &quo ...
- Gson解析的小例子
最近解析些复杂的节点数据解析,用安卓自带的json解析比较麻烦所以只能用Gson解析,所以从网上下了点demo来看看 http://blog.csdn.net/tkwxty/article/detai ...
- Android网络之数据解析----使用Google Gson解析Json数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Gson解析Json格式数据
//数据定义:=========================================== class User{ String name; String password; String ...
随机推荐
- baidu手机浏览器安卓4.5版公布:由于快,所以爱
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDUyMzk4OA==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- C语言面试题2
预处理 问题1:什么是预编译?何时需要预编译? 答:预编译又称预处理,是整个编译过程最先做的工作,即程序执行前的一些预处理工作.主要处理#开头的指令.如拷贝#include包含的文件代码.替换#def ...
- curl 知识点
curl :command line tool and library for transferring data with URLs curl 命令,常用缩写: curl 命令 缩写 说明 curl ...
- centos 使用mutt发送邮件带附件
1.安装mutt工具 yum install -y mutt 2.使用mutt发邮件并带附件echo "统计日志" | /usr/bin/mutt -s "统计日志&qu ...
- POJ2411骨牌覆盖——状压dp
题目:http://poj.org/problem?id=2411 状压dp.注意一下代码中标记的地方. #include<iostream> #include<cstdio> ...
- Maven 生成项目站点
Maven 不仅仅时一个自动化构建工具和一个依赖管理工具,他还能够帮助聚合项目信息,促进团队间的交流,POM 可以包含各种项目信息,如项目描述.版本控制系统地址.缺陷跟踪系统地址.许可证信息.开发者信 ...
- 关于lidroid xUtils 开源项目
最近搜了一些框架供初学者学习,比较了一下XUtils是目前git上比较活跃 功能比较完善的一个框架,是基于afinal开发的,比afinal稳定性提高了不少,下面是介绍: xUtils简介 xUtil ...
- Spring AOP的注解方式实现
spring也支持注解方式实现AOP,相对于配置文件方式,注解配置更加的轻量级,配置.修改更加方便. 1.开启AOP的注解配置方式 <!-- 开启aop属性注解 --> <aop:a ...
- 1082 Read Number in Chinese (25 分)
1082 Read Number in Chinese (25 分) Given an integer with no more than 9 digits, you are supposed to ...
- Maven web项目启动出错
问题描述: 在第一次建立maven项目后,启动测试,结果jsp页面报告404错误 问题解决: 在pom.xml中引入servlet-api 和 jsp-api,maven不会自动的添加,因此,要在首次 ...