Gson 是google解析Json的一個(gè)開源框架,同類的框架fastJson,JackJson等等
本人fastJson用了兩年,也是從去年才開始接觸Gson,希望下面的總結(jié)會(huì)對博友有用,至于Gson與FastJson的對比,其實(shí)半斤八兩的問題,不再贅述
第一步:在AS下面創(chuàng)建java工程 并添加gson依賴
compile 'com.google.code.gson:gson:2.6.2'

Gson的實(shí)例化方式:
1:Gson gson=newGson();
2:通過GsonBuilder 可以配置多種選項(xiàng)
.enableComplexMapKeySerialization()//支持Map的key為復(fù)雜對象的形式 .serializeNulls() //智能null .setPrettyPrinting()// 調(diào)教格式 .disableHtmlEscaping() //默認(rèn)是GSON把HTML 轉(zhuǎn)義的
Gson的基本用法:
JavaBean轉(zhuǎn)換Json字符串
gson提供 publicString toJson(Object src) 方法可以將對象轉(zhuǎn)換成jsonStr
import com.google.gson.Gson; * @email xuanyouwu@163.com public static class Student { private static void log(String msg) { public static void main(String[] args) throws Exception { Student student = new Student(); student.setName("xuanyouwu"); String jsonStr = gson.toJson(student); log("---->javabean convert jsonStr:" + jsonStr);
運(yùn)行結(jié)果:
---->javabean convert jsonStr:{"name":"xuanyouwu","age":26}
List Map轉(zhuǎn)Json字符串
import com.google.gson.Gson; import java.util.HashMap; * @email xuanyouwu@163.com private static void log(String msg) { public static void main(String[] args) throws Exception { 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));
運(yùn)行結(jié)果:
---->list convert jsonStr:["1","a","3","rt","5"] ---->map convert jsonStr:{"name":"xuanyouwu","age":"26"}
Json字符串轉(zhuǎn)JavaBean
String studentJsonStr="{\"name\":\"xuanyouwu\",\"age\":26}"; Student student1 = gson.fromJson(studentJsonStr, Student.class); log("------->json convert JavaBean:"+student1);
運(yùn)行結(jié)果:
------->json convert JavaBean:Student{name='xuanyouwu', age=26}
Json字符串轉(zhuǎn)List
String listJsonStr="[\"1\",\"a\",\"3\",\"rt\",\"5\"]";
Type type = new TypeToken<ArrayList<String>>() { ArrayList<String> sList=gson.fromJson(listJsonStr, type); log("------->json convert List:"+sList);
運(yùn)行結(jié)果:
------->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里面有一個(gè)非常有意思的抽象基類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 其實(shí)就是null 字段
JsonNull jsonNull=new JsonNull();//構(gòu)造方法過時(shí),推薦INSTANCE
JsonNull jsonNull=JsonNull.INSTANCE;
運(yùn)行結(jié)果:
-----null
JsonPrimitive非常有意思,我們知道如果json轉(zhuǎn)換成字符串 可能包含引號(hào)的轉(zhuǎn)義,但是通過JsonPrimative我們可以獲得為轉(zhuǎn)義的字符串,看實(shí)例:
import com.google.gson.JsonNull; import com.google.gson.JsonPrimitive; * @email xuanyouwu@163.com private static void log(String 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());
運(yùn)行結(jié)果:
------>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

創(chuàng)建JsonObject
通過addPropert(key,value)可以向jsonObject中添加字段 跟hashMap類似
JsonObject jsonObject=new JsonObject(); jsonObject.addProperty("name","xuanyouwu"); jsonObject.addProperty("age",26); log("------>create jsonObject:"+jsonObject);
運(yùn)行結(jié)果:
------>create jsonObject:{"name":"xuanyouwu","age":26}
創(chuàng)建JsonArray
JsonArray jsonElements=new JsonArray(); log("------>create jsonArray:"+jsonElements);
運(yùn)行結(jié)果:
------>create jsonArray:["a","b","c","d"]
JsonObject 嵌套數(shù)組或者說嵌套JsonArray
通過JsonObject的add(key,JsonElement)可以為jsonObject 添加一個(gè)數(shù)組的字段
JsonObject jsonObject2=new JsonObject(); jsonObject2.addProperty("name","xuanyouwu"); jsonObject2.addProperty("age",26); JsonArray jsonElements2=new JsonArray(); jsonElements2.add("打游戲"); jsonElements2.add("看電視"); jsonObject2.add("hobby",jsonElements2); log("------>create jsonObject inner JsonArray:"+jsonObject2);
運(yùn)行結(jié)果:
------>create jsonObject inner JsonArray:{"name":"xuanyouwu","age":26,"hobby":["騎車","打游戲","看電視"]}
Gson注解
在Gson中有五類注解

重命名注解:SerializedName
作用:轉(zhuǎn)換關(guān)鍵字key,json轉(zhuǎn)換成JavaBean時(shí),json字段的key 默認(rèn)必須和我們聲明類的字段名稱一樣,當(dāng)服務(wù)器端返回了關(guān)鍵字怎么辦,比如key 為new switch這樣,我們 在聲明類的時(shí)候不能寫這樣的字段,可能你想服務(wù)器端改動(dòng),他可能要改數(shù)據(jù)庫,但是我告訴你,做服務(wù)端的大部分不愿意改動(dòng)他的json,是很自私的!這時(shí)候重命名注解都排上用場了 第二種場景:服務(wù)器端返回的json 的key 簡直太丑,或者太長,你想簡化,my_parent_name,可以簡化成mpn
比較優(yōu)雅簡介
實(shí)例:
import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\n" + " \"name\": \"zhangsan\",\n" + User user = gson.fromJson(jsonFromServer, User.class); log("------>user:" + user);
運(yùn)行結(jié)果: ------>user:User{name='zhangsan', age=26, isnew=1}
import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; * @email xuanyouwu@163.com private static void log(String msg) { public static class User2 { @SerializedName("my_parent_name") public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer2="{\n" + " \"my_parent_name\": \"zhangsanf\",\n" + " \"name\": \"zhangsan\"\n" + User2 user2 = gson2.fromJson(jsonFromServer2, User2.class); log("------>user2:" + user2);
運(yùn)行結(jié)果: ------>user2:User2{name='zhangsan', age=26, pn='zhangsanf'}
作用2:結(jié)合alternate 提供多種備用字段key來解析,@SerializedName(value ="desc",alternate
= {"other","note"})
如果json中有other就會(huì)解析成desc 如果有note也會(huì)解析成desc,注意1:value中的值不能出現(xiàn)在alternate中,注意2:alternate的備選字段 會(huì)后面的替換前面的
實(shí)例:
import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { @SerializedName(value = "desc",alternate = {"other","note"}) public String toString() { ", desc='" + desc + '\'' + public static void main(String[] args) throws Exception { String jsonFromServer = "{\n" + " \"other\": \"成都人\",\n" + " \"name\": \"zhangsan\"\n" + User user = gson.fromJson(jsonFromServer, User.class); log("------>user:" + user); String jsonFromServer2 = "{\n" + " \"note\": \"成都人\",\n" + " \"name\": \"zhangsan\"\n" + User user2 = gson.fromJson(jsonFromServer2, User.class); log("------>user:" + user2); //包括desc 與note note在desc之后 String jsonFromServer3="{\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" + " \"note\": \"note成都人\",\n" + " \"name\": \"zhangsan\",\n" + " \"desc\": \"desc成都人\"\n" + User user4 = gson.fromJson(jsonFromServer4, User.class); log("------>user:" + user4);
運(yùn)行結(jié)果:
------>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過濾注解
源碼:默認(rèn)既可以序列化又可以反序列化
@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()
不添加@Expose注解的字段將不會(huì)解析:
分為以下幾種情況:
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) 既可以序列化,也可以反序列化
實(shí)例:將分別演示這四種情況
不添加@Expose注解:等同于@Expose(deserialize = false,serialize = false)
import com.google.gson.Gson; import com.google.gson.GsonBuilder; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\"name\": \"zhangsan\"}"; Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() User user = gson.fromJson(jsonFromServer, User.class); log("------>反序列化:" + user); user1.name = "zhangsan2"; String userStr = gson.toJson(user1); log("------>序列化:" + userStr);
運(yùn)行結(jié)果:
------>反序列化:User{name='null'}
------>序列化:{}
添加@Expose注解
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Expose; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { @Expose //等同于 @Expose(deserialize = true,serialize = true) public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\"name\": \"zhangsan\"}"; Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() User user = gson.fromJson(jsonFromServer, User.class); log("------>反序列化:" + user); user1.name = "zhangsan2"; String userStr = gson.toJson(user1); log("------>序列化:" + userStr);
運(yùn)行結(jié)果:
------>反序列化:User{name='zhangsan'}
------>序列化:{"name":"zhangsan2"}
@Expose注解 只序列化
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Expose; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { @Expose(deserialize = false,serialize = true) public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\"name\": \"zhangsan\"}"; Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() User user = gson.fromJson(jsonFromServer, User.class); log("------>反序列化:" + user); user1.name = "zhangsan2"; String userStr = gson.toJson(user1); log("------>序列化:" + userStr);
運(yùn)行結(jié)果:
------>反序列化:User{name='null'}------>序列化:{"name":"zhangsan2"}
@Expose 只反序列化
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Expose; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { @Expose(deserialize = true, serialize = false) public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\"name\": \"zhangsan\"}"; Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() User user = gson.fromJson(jsonFromServer, User.class); log("------>反序列化:" + user); user1.name = "zhangsan2"; String userStr = gson.toJson(user1); log("------>序列化:" + userStr);
運(yùn)行結(jié)果:
------>反序列化:User{name='zhangsan'}
------>序列化:{}
@Since(float v)注解 版本控制
結(jié)合GsonBuilder.setVersion(n)使用 當(dāng)n>=v時(shí) 才會(huì)序列化解析
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Since; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\"name\": \"zhangsan\"}"; Gson gson = new GsonBuilder() 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() 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() 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);
運(yùn)行結(jié)果:
------>反序列化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)注解 版本控制
當(dāng)gson的setVersion(n) n<v 才解析
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Until; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { public String toString() { public static void main(String[] args) throws Exception { String jsonFromServer = "{\"name\": \"zhangsan\"}"; Gson gson = new GsonBuilder() 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() 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() 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);
運(yùn)行結(jié)果:
------>反序列化v=1:User{name='zhangsan'}
------>序列化v=1:{"name":"zhangsan2"}
------>反序列化v=2:User{name='null'}
------>序列化v=2:{}
------>反序列化v=3:User{name='null'}
------>序列化v=3:{}
Gson 高級(jí)用法
相信看過retrofit2.0 源碼的同學(xué)都知道,其中有一個(gè)GsonConverterFactory 里面的用法十分精煉老成,這里來一段源碼


據(jù)說使用TypeAdapter 效率更高,本人還未對比測試,暫時(shí)放后吧,TypeAdapter是什么玩意呢?
在源碼中備注了一句 Converts Java objects to and from JSON 就是對象json之間的互相轉(zhuǎn)換 接替了T 泛型類的序列化和反序列化的邏輯
從源碼中我們看到區(qū)分了2.1版本之前后之后的用法,2.1版本之前可以自定義adapter:
public class PointAdapter extends TypeAdapter<Point> { * public Point read(JsonReader reader) throws IOException { * if (reader.peek() == JsonToken.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 { * String xy = value.getX() + "," + value.getY();
使用
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); // And an example for serialization: <pre> {@code // Graph graph = new Graph(...); // TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class); // String json = graphAdapter.toJson(graph);
實(shí)例:使用TypeAdapter 來序列化和反序列化
import com.google.gson.Gson; import com.google.gson.TypeAdapter; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { public String toString() { public static void main(String[] args) throws Exception { TypeAdapter<User> userTypeAdapter = gson.getAdapter(User.class); String userJsonStr = userTypeAdapter.toJson(user); log("------>序列化:" + userJsonStr); User user1 = userTypeAdapter.fromJson(userJsonStr); log("------>反序列化:" + user1);
運(yùn)行結(jié)果:
------>序列化:{"name":"xuanyouwu","age":26} ------>反序列化:User{name='xuanyouwu', age=26}
Gson的容錯(cuò)機(jī)制:
為什么要容錯(cuò)了,在javaBean中聲明了int類型的age 如果服務(wù)端 返回的是"" 空字符串怎么辦呢?崩潰?
如果json格式不規(guī)范如 {name=zhangsan,age:26,hobby=null} 發(fā)現(xiàn)不是普通的key value
容錯(cuò)實(shí)現(xiàn)方式1:
1:創(chuàng)建Gson的方式
2:使用JsonReader
JsonReader jsonReader = gson.newJsonReader(value.charStream()); jsonReader.<span style="font-family: 宋體; font-size: 9pt;">setLenient(true)</span>
3:自定義TypeAdapter
4:使用注解JsonAdapter,其實(shí)也是自定義Adapter
1.2歸為一類 由框架實(shí)現(xiàn),基本json大格式規(guī)范,鍵值對不標(biāo)準(zhǔn),多引號(hào)的問題等等,而不報(bào)錯(cuò)停止解析,但是功能相對較弱
能解決bug
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON
3,4歸為一類,都屬于自定義adapter,但是3與gson綁定,4使用注解和字段綁定
實(shí)例:
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; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { public String toString() { public static class UserTypeAdapter extends TypeAdapter<User> { public void write(JsonWriter out, User value) throws IOException { out.name("name").value(value.name); out.name("age").value(value.age); public User read(JsonReader in) throws IOException { user.name = in.nextString(); String str = in.nextString(); user.age = Integer.valueOf(str); public static void main(String[] args) throws Exception { String jsonStrFromServer = "{\n" + " \"name\": \"zhangsan\"\n" + log("------->jsonFromServer:"+jsonStrFromServer); User user = gson.fromJson(jsonStrFromServer, User.class); log("------>默認(rèn)Gson 解析:" + user); } catch (JsonParseException e) {//java.lang.NumberFormatException: empty String log("------>默認(rèn)Gson 解析 異常:" + e); Gson gson2 = new GsonBuilder() .registerTypeAdapter(User.class, new UserTypeAdapter()).create(); User user2 = gson2.fromJson(jsonStrFromServer, User.class); log("------>自定義adapter 解析:" + user2); } catch (JsonParseException e) {//java.lang.NumberFormatException: empty String log("------>自定義adapter 異常:" + e); UserTypeAdapter userTypeAdapter = new UserTypeAdapter(); User user3 = userTypeAdapter.fromJson(jsonStrFromServer); log("------>自定義adapter 解析2:" + user3); log("------>自定義adapter 異常2:" + e);
運(yùn)行結(jié)果:
------->jsonFromServer:{
"age": "",
"name": "zhangsan"
}
------>默認(rèn)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; * @email xuanyouwu@163.com private static void log(String msg) { public static class User { @JsonAdapter(IntegerTypeAdapter.class) public String toString() { public static class IntegerTypeAdapter extends TypeAdapter<Integer> { public void write(JsonWriter out, Integer value) throws IOException { public Integer read(JsonReader in) throws IOException { String str = in.nextString(); i = Integer.valueOf(str); public static class User2 { public String toString() { public static void main(String[] args) throws Exception { String jsonStrFromServer = "{\n" + " \"name\": \"zhangsan\"\n" + log("------->jsonFromServer:" + jsonStrFromServer); User2 user2 = gson.fromJson(jsonStrFromServer, User2.class); log("------>gson 解析:" + user2); log("------>gson 解析異常:" + e); User user = gson.fromJson(jsonStrFromServer, User.class); log("------>JsonAdapter 注解 解析:" + user); } catch (JsonParseException e) {//java.lang.NumberFormatException: empty String log("------>JsonAdapter 注解 異常:" + e);
運(yùn)行結(jié)果:
------>gson 解析異常:com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String ------>JsonAdapter 注解 解析:User{name='zhangsan', age=0}
可以看到我們成功地跳過服務(wù)端返回json不合理的坑了吧
</pre><pre code_snippet_id="1687762" snippet_file_name="blog_20160519_47_1535429" name="code" class="java">不得不吐槽啊,像這種服務(wù)器端錯(cuò)誤,應(yīng)該完全歸結(jié)服務(wù)端json不合理返回,
往往老板都會(huì)找客戶端原因,怎么又崩潰了?怎么又不顯示了?老板不會(huì)關(guān)心是不是數(shù)據(jù)返回不合理的問題的!
做客戶端需要相當(dāng)?shù)某惺苣芰?同意的點(diǎn)個(gè)贊哈
</pre><p>其實(shí)上面的方式保險(xiǎn)是很保險(xiǎn),但是需要維護(hù)的地方多,代碼量大,我們介紹另外一種方式:JsonSerializer與JsonDeserializer 之關(guān)系單方面的處理,可以全局注冊某個(gè)類型的處理:看實(shí)例:</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; * @email xuanyouwu@163.com public class GsonTest10 { private static void log(String msg) { public static class User { public String toString() { public static void main(String[] args) throws Exception { JsonDeserializer<Integer> jsonDeserializer = new JsonDeserializer<Integer>() { public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { } catch (NumberFormatException e) { Gson gson = new GsonBuilder() .registerTypeAdapter(int.class, jsonDeserializer) String jsonStrFromServer = "{\n" + " \"name\": \"zhangsan\"\n" + log("------->jsonFromServer:" + jsonStrFromServer); User user = gson.fromJson(jsonStrFromServer, User.class); log("------> JsonDeserializer<Integer> 解析:" + user); log("------> JsonDeserializer<Integer> 解析異常:" + e); User user1 = gson1.fromJson(jsonStrFromServer, User.class); log("------> 默認(rèn)gson 解析:" + user1); log("------> 默認(rèn)gson 解析異常:" + e);
運(yùn)行結(jié)果:
------->jsonFromServer:{
"age": "",
"name": "zhangsan"
}
------> JsonDeserializer<Integer> 解析:User{name='zhangsan', age=0}
------> 默認(rèn)gson 解析異常:com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String
這樣定義全局的反序列化工具就能避免解析異常
|