Json解析2--Gson解析详解

本文参考自:http://blog.csdn.net/axuanqq/article/details/51441590和http://blog.csdn.net/qxs965266509/article/details/42774691


Gson是google解析Json的一个开源框架,同类的框架fastJson,JackJson等等,至于Gson与FastJson的对比,其实半斤八两的问题,不再赘述
gson-2.6.2.jar下载地址:点击打开链接


一、Gson的实例化方式:
1.Gson gson=newGson();
2.通过GsonBuilder 可以配置多种选项
gson = new GsonBuilder()  
                   .setLenient()// json宽松  
                   .enableComplexMapKeySerialization()//支持Map的key为复杂对象的形式  
                   .serializeNulls() //智能null  
                   .setPrettyPrinting()// 调教格式  
                   .disableHtmlEscaping() //默认是GSON把HTML 转义的  
                   .create();


二、Gson的基本用法:
在Java开发中,有时需要保存一个数据结构成字符串,可能你会考虑用Json,但是当Json字符串转换成Java对象时,转换成的是JsonObject,并不是你想要的Class类型的对象,操作起来就很不是愉悦,下面说的就可以解决了这种问题。
现在,我先自定义一个Class类

import java.util.ArrayList;
import java.util.HashMap;

public class Student {  
    public int id;  
    public String nickName;
    public String email;
    public int age;  
    public ArrayList<String> books;  
    public HashMap<String, String> booksMap;  
}
案例一,案例二,案例三都是把Java的Class对象使用Gson转换成Json的字符串
案例一:
仅包含基本数据类型的数据结构
Gson gson = new Gson();  
Student student = new Student();  
student.id = 1;  
student.nickName = "乔晓松";  
student.age = 22;  
student.email = "965266509@qq.com";  
System.out.println(gson.toJson(student));
输出结果是:
{"id":1,"nickName":"乔晓松","email":"965266509@qq.com","age":22}

案例二:
除了基本数据类型还包含了List集合
Gson gson = new Gson();  
Student student = new Student();  
student.id = 1;  
student.nickName = "乔晓松";  
student.age = 22;  
student.email = "965266509@qq.com";  
ArrayList<String> books = new ArrayList<String>();  
books.add("数学");  
books.add("语文");  
books.add("英语");  
books.add("物理");  
books.add("化学");  
books.add("生物");  
student.books = books;  
System.out.println(gson.toJson(student));
输出结果是:
{"id":1,"nickName":"乔晓松","email":"965266509@qq.com","age":22,"books":["数学","语文","英语","物理","化学","生物"]}


案例三:
除了基本数据类型还包含了List和Map集合

Gson gson = new Gson();  
Student student = new Student();  
student.id = 1;  
student.nickName = "乔晓松";  
student.age = 22;  
student.email = "965266509@qq.com";  
ArrayList<String> books = new ArrayList<String>();  
books.add("数学");  
books.add("语文");  
books.add("英语");  
books.add("物理");  
books.add("化学");  
books.add("生物");  
student.books = books;  
HashMap<String, String> booksMap = new HashMap<String, String>();  
booksMap.put("1", "数学");  
booksMap.put("2", "语文");  
booksMap.put("3", "英语");  
booksMap.put("4", "物理");  
booksMap.put("5", "化学");  
booksMap.put("6", "生物");  
student.booksMap = booksMap;  
System.out.println(gson.toJson(student));
输出结果是 :
{"id":1,"nickName":"乔晓松","email":"965266509@qq.com","age":22,"books":["数学","语文","英语","物理","化学","生物"],"booksMap":{"3":"英语","2":"语文","1":"数学","6":"生物","5":"化学","4":"物理"}}


案例四:
把案例三输出的字符串使用Gson转换成Student对象

Gson gson = new Gson();  
Student student = new Student();  
student.id = 1;  
student.nickName = "乔晓松";  
student.age = 22;  
student.email = "965266509@qq.com";  
ArrayList<String> books = new ArrayList<String>();  
books.add("数学");  
books.add("语文");  
books.add("英语");  
books.add("物理");  
books.add("化学");  
books.add("生物");  
student.books = books;  
HashMap<String, String> booksMap = new HashMap<String, String>();  
booksMap.put("1", "数学");  
booksMap.put("2", "语文");  
booksMap.put("3", "英语");  
booksMap.put("4", "物理");  
booksMap.put("5", "化学");  
booksMap.put("6", "生物");  
student.booksMap = booksMap;  
String result = gson.toJson(student);  

Student studentG = gson.fromJson(result, Student.class);  

System.out.println("id:" + studentG.id);
System.out.println("nickName:" + studentG.nickName);  
System.out.println("age:" + studentG.age);  
System.out.println("email:" + studentG.email);  
System.out.println("books size:" + studentG.books.size());  
System.out.println("booksMap size:" + studentG.booksMap.size());
输出结果是 :
id:1
nickName:乔晓松
age:22
email:965266509@qq.com
books size:6
booksMap size:6


通过这4个案例我解决你一定就把Gson的基本用法学会了,当然我们的需求可能需要把List或者Map等集合的泛型换成我们自定义个class,这也是可以解决的,请看案例
案例五:泛型的使用(好像这个也不叫做泛型吧)

import java.util.HashMap;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class haha {
    public static class Book{
    	public int id;
        public String name;
    	public Book(int id,String name){
    		this.id=id;
    		this.name=name;
    	}
    }
    
    public static void main(String args[]){
        Gson gson = new Gson();  
        Map<String, Book> booksMap = new HashMap<>();
        booksMap.put("book1", new Book(1, "Java基础开发"));
        booksMap.put("book2", new Book(2, "Java设计模式"));
        booksMap.put("book3", new Book(3, "Java算法"));
        String dataStr = gson.toJson(booksMap);
        System.out.println("dataStr:" + dataStr);
        HashMap<String, Book> booksMap2 = gson.fromJson(dataStr, new TypeToken<HashMap<String, Book>>() {  
        }.getType());  
        for (Map.Entry<String, Book> entry : booksMap2.entrySet()) {  
            System.out.println("key:"+entry.getKey()+"    value:Book{id="+entry.getValue().id
            		+", name='"+entry.getValue().name+"'}"); 
        }
    }
}
运行结果是:
dataStr:{"book3":{"id":3,"name":"Java算法"},"book1":{"id":1,"name":"Java基础开发"},"book2":{"id":2,"name":"Java设计模式"}}
key:book3    value:Book{id=3, name='Java算法'}
key:book1    value:Book{id=1, name='Java基础开发'}
key:book2    value:Book{id=2, name='Java设计模式'}


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

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;
		public void setName(String name) {
			this.name = name;
		}
		public String getName() {
			return this.name;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public int getAge(){
			return this.age;
		}
    }  

    private static void log(String msg) {  
        System.out.println(msg);  
    }  

    public static void main(String[] args) throws Exception {  
        Gson gson = new Gson();
        //JavaBean转换Json字符串
        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}



下面是它的四种用法:

import com.google.gson.Gson;  
import com.google.gson.JsonNull;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  

import json.GsonTest1.Student;
  
/** 
 * @author xuanyouwu 
 * @email xuanyouwu@163.com 
 * @time 2016-05-18 10:39 
 */  
public class GsonTest2 {

    private static void log(String msg) {  
        System.out.println(msg);
    }

    public static void main(String[] args) throws Exception {  
        Gson gson = new Gson();
  
        //List Map转Json字符串
//        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));
        
        //Json字符串转JavaBean,没整明白这个有什么效果,转成的JavaBean在哪里呢。。。
//        String studentJsonStr="{\"name\":\"xuanyouwu\",\"age\":26}";  
//        Student student1 = gson.fromJson(studentJsonStr, Student.class);  
//        log("------->json convert JavaBean:"+student1);
        
        //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);
        
        //JsonNull其实就是null字段
        JsonNull jsonNull=JsonNull.INSTANCE;  
        log("-----"+jsonNull);
    }  
}
JsonPrimitive非常有意思,我们知道如果json转换成字符串 可能包含引号的转义,但是通过JsonPrimative我们可以获得为转义的字符串,看实例:
import com.google.gson.JsonPrimitive;
  
/** 
 * @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 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和JsonArray的用法:
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

public class GsonTest4 {
    private static void log(String msg) {
        System.out.println(msg);
    }
    public static void main(String[] args) throws Exception {
    	//创建JsonObject,通过addPropert(key,value)可以向jsonObject中添加字段 跟hashMap类似
//    	JsonObject jsonObject=new JsonObject();  
//    	jsonObject.addProperty("name","xuanyouwu");  
//    	jsonObject.addProperty("age",26);  
//    	log("------>create jsonObject:"+jsonObject);
    	
    	//创建JsonArray
//    	JsonArray jsonElements=new JsonArray();  
//    	jsonElements.add("a");  
//    	jsonElements.add("b");  
//    	jsonElements.add("c");  
//    	jsonElements.add("d");  
//    	log("------>create jsonArray:"+jsonElements);
    	
    	//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);
    }
}
三、Gson注解,在Gson中有五类注解

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

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 GsonTest5 {  
    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}
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 GsonTest6 {  
    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的备选字段 会后面的替换前面的
实例:
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 GsonTest7 {  
    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;  
}
不添加@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)

import com.google.gson.Gson;  
import com.google.gson.GsonBuilder;  
  
/** 
 * @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;  
  
        @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注解

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 GsonTest9 {  
    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注解 只序列化

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 GsonTest10 {  
    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"}

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 GsonTest11 {  
    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时才会序列化解析

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 GsonTest12 {  
    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 才解析
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 GsonTest13 {  
    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 来序列化和反序列化
import com.google.gson.Gson;  
import com.google.gson.TypeAdapter;  
  
/** 
 * @author xuanyouwu 
 * @email xuanyouwu@163.com 
 * @time 2016-05-18 11:20 
 */  
public class GsonTest14 {  
    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());
3.自定义TypeAdapter
4.使用注解JsonAdapter,其实也是自定义Adapter

1,2归为一类,由框架实现,基本json大格式规范,键值对不标准,多引号的问题等等,而不报错停止解析,但是功能相对较弱能解决bug
3,4归为一类,都属于自定义adapter,但是3与gson绑定,4使用注解和字段绑定
 实例:

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 GsonTest15 {  
    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是空字符串 但是不影响整体的解析流程,这对客户端是十分友好的

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

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 GsonTest16 {  
    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不合理的坑了吧,不得不吐槽啊,像这种服务器端错误,应该完全归结服务端json不合理返回,往往老板都会找客户端原因,怎么又崩溃了?怎么又不显示了?老板不会关心是不是数据返回不合理的问题的!做客户端需要相当的承受能力哈,同意的点个赞哈
其实上面的方式保险是很保险,但是需要维护的地方多,代码量大,我们介绍另外一种方式:JsonSerializer与JsonDeserializer 之关系单方面的处理,可以全局注册某个类型的处理:看实例:

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 GsonTest17 {  
    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


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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值