本文参考自: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
这样定义全局的反序列化工具就能避免解析异常