項(xiàng)目中一直使用的原生解析JSONObject.
參考鏈接http://www.itdecent.cn/p/e740196225a4#
基于Gson V2.8.5
序列化: 把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程。 eg:toJson(對(duì)象)
反序列化:把字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程。eg:fromJson("字節(jié)序列",對(duì)象)
Gson基本用法
-
toJson序列化.
public String toJson(Object src) {
public String toJson(Object src, Type typeOfSrc) {}
public void toJson(Object src, Appendable writer) throws JsonIOException {}
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {}
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {}
public String toJson(JsonElement jsonElement) {}
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {}
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {}
-
fromJson反序列化.
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {}
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {}
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {}
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {}
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {}
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {}
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {}
基本數(shù)據(jù)類型的生成、
Gson gson=new Gson();
String jsonString=gson.toJson("java");//java
String jsonNumber=gson.toJson(2018);//2018
String jsonBoolean=gson.toJson(true);//true
POJO類的生成與解析普通java類
String jsonResponse="{
"code": 200,
"msg": "OK",
"user": [
{
"name": "cqx1",
"age": "2018",
"phone": "166...111",
"email": "183xxxx111@qq.com"
},
{
"name": "cqx2",
"age": "2018",
"phone": "166...222",
"email": "183xxxx222@qq.com"
}
]
}";
private class StudentEntity {
private String code;
@Expose
private String msg;
/**
* 此處user為json串的key,下面的userList為自己定義的別名
*/
@SerializedName("user")
private List<UserEntity> userList;
private class UserEntity {
private String name;
private String age;
private String phone;
private String emails;
...
如果此時(shí)按照以下解析,哪怕try catch也攔截不到。
/**
* 從raw包下讀取數(shù)據(jù)
* @param context
* @param rawName R.raw.cqx
* @return
*/
public static String getFileStremFromRaw(Activity context, int rawName) {
try {
InputStreamReader inputReader = new InputStreamReader(context.getResources().openRawResource(rawName));
BufferedReader bufReader = new BufferedReader(inputReader);
String line = "";
String Result = "";
while ((line = bufReader.readLine()) != null)
Result += line;
return Result;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
解析上面的報(bào)文。
private void parseJsonReponse() {
String response = FileTools.getFileStremFromRaw(this, R.raw.test);
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = jsonParser.parse(response).getAsJsonObject();
try {
//因?yàn)閷?duì)應(yīng)的為Object,所以這樣的解析就會(huì)異常崩潰,并且攔截?zé)o用。
JsonArray jsonArray = jsonParser.parse(response).getAsJsonArray();
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
String msg=jsonObject.get("msg").getAsString();
}
錯(cuò)誤日志如下:
Caused by: java.lang.IllegalStateException: Not a JSON Array: {"code":200,"msg":"OK","user":[{"name":"cqx1","age":"2018","phone":"166...111","email":"183xxxx111@qq.com"},{"name":"cqx2","age":"2018","phone":"166...222","email":"183xxxx222@qq.com"}]}
at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:107)
at com.cc.rxjava.gson.GsonActivity.parseJsonReponse(GsonActivity.java:76)
at com.cc.rxjava.gson.GsonActivity.onCreate(GsonActivity.java:68)
at android.app.Activity.performCreate(Activity.java:6715)
然后實(shí)際開(kāi)發(fā)中,后臺(tái)返回的json格式可能跟我們要的不一致,如果線上的因?yàn)楹笈_(tái)返回的數(shù)據(jù)格式而崩潰,哪怕最終查出原因是后臺(tái)的問(wèn)題,最終客戶端還是得背鍋,誰(shuí)叫沒(méi)有做容錯(cuò)處理呢。
如果服務(wù)端返回的為正確的數(shù)據(jù)解析方式:
private void parseJsonReponse() {
String response = FileTools.getFileStremFromRaw(this, R.raw.test);
StudentEntity studentEntity = new Gson().fromJson(response, StudentEntity.class);
Type type =new TypeToken<StudentEntity>(){}.getType();
StudentEntity studentEntity2 = new Gson().fromJson(response, type);
// userList = studentEntity.userList;
}
json的生成
將對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程。toJson
Gson gson = new Gson();
UserEntity user = new UserEntity("cc","2018","1660....","183...@qq.com");
String jsonObject = gson.toJson(user);//{"age":"2018","emails":"183...@qq.com","name":"cc","phone":"1660...."}
解析Json
將字節(jié)系列轉(zhuǎn)為為對(duì)象的過(guò)程。fromJson
UserEntity userEntity = gson.fromJson(jsonObject, UserEntity.class);
List<UserEntity> list = gson.fromJson(jsonArray, new TypeToken<List<UserEntity>>() {
}.getType());
數(shù)組
String[] strings = gson.fromJson(jsonArray, String[].class);
List
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
@Expose、@SerializeName注解
json解析的字段(key)的名稱和類型是一一對(duì)應(yīng)的,當(dāng)客戶端和后臺(tái)使用的語(yǔ)言不同,二者語(yǔ)言命名規(guī)范不同,命名規(guī)則常常不統(tǒng)一的情況下,使用@Expose和@SerializeName注解。
@Expose注解:區(qū)分實(shí)體中序列號(hào)的屬性,包含兩個(gè)屬性,deserialize(反序列化)和serialize(序列化),默認(rèn)為true。使用@Expose進(jìn)行序列化,如果不想被序列化也可以使用transient。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code true}.
* @since 1.4
*/
public boolean serialize() default true;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code true}.
* @since 1.4
*/
public boolean deserialize() default true;
}
@SerializeName注解:屬性重命名
//使用這樣的方式創(chuàng)建gson對(duì)象。
Gson gson=new Gson().newBuilder().excludeFieldsWithoutExposeAnnotation().create();
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface SerializedName {
/**
* @return the desired name of the field when it is serialized or deserialized
*/
String value();
/**
* @return the alternative names of the field when it is deserialized
*/
String[] alternate() default {};
}
用例
@SerializedName("email_address")
public String emailAddress;
如果存在一個(gè)key多個(gè)寫(xiě)法,則可以選擇@SerializeName的alternate別名的選擇,根據(jù)以上代碼可知為一個(gè)字符串?dāng)?shù)組。
借用例子
{"name":"怪盜kidou","age":24,"emailAddress":"ikidou@example.com"}
{"name":"怪盜kidou","age":24,"email_address":"ikidou@example.com"}
{"name":"怪盜kidou","age":24,"email":"ikidou@example.com"}
作者:怪盜kidou
鏈接:http://www.itdecent.cn/p/e740196225a4#
所以處理辦法是:
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
多個(gè)情況同時(shí)存在時(shí):
Gson gson = new Gson();
String json = "{\"name\":\"怪盜kidou\",\"age\":24,\"emailAddress\":\"ikidou_1@example.com\",\"email\":\"ikidou_2@example.com\",\"email_address\":\"ikidou_3@example.com\"}";
User user = gson.fromJson(json, User.class);
System.out.println(user.emailAddress); // ikidou_3@example.com
作者:怪盜kidou
鏈接:http://www.itdecent.cn/p/e740196225a4#
補(bǔ)充demo

。
如上圖可以看到該json格式為外層JsonObject,里面有個(gè)key為rltInfo的JsonObject,rltInfo里面存在兩個(gè)JsonArray的數(shù)組list.可以簡(jiǎn)易封裝一下解析:
//基類
public class BaseResult<T> {
public boolean rltFlag;
public RltInfoEntity<T> rltInfo;
}
public class RltInfoEntity<T> {
public String status;
public String statusDesc;
@SerializedName("taskList")
public List<T> mGcTaskList;
//mShTaskList客戶端命名規(guī)則,shTaskList為服務(wù)端返回來(lái)的json的key
@SerializedName("shTaskList")
public List<T> mShTaskList;
}
/**
* created by cheng.qx on 2018/8/20 17:10
*/
public class XJTaskEntity {
/**
* 任務(wù)ID
*/
private String taskId;
/**
* 任務(wù)名稱
*/
private String taskName;
/**
* 所屬用戶ID
*/
private String personId;
/**
* 所屬用戶名稱
*/
private String personName;
/**
* 門店ID
*/
private String storeId;
/**
* 門店名稱
*/
@SerializedName("orgName")
private String storeName;
/**
* 區(qū)域ID
*/
private String areaId;
/**
* 區(qū)域名稱
*/
private String areaName;
/**
* 任務(wù)開(kāi)始時(shí)間-天
*/
@SerializedName(value ="beginTimeStr",alternate={"submitTimeStr"})
private String taskBeginDay;
/**
* 任務(wù)開(kāi)始時(shí)間-時(shí)分秒
*/
private String taskBeginHour;
/**
* 任務(wù)結(jié)束時(shí)間-天
*/
@SerializedName("endTimeStr")
private String taskEndDay;
/**
* 任務(wù)結(jié)束時(shí)間-時(shí)分秒
*/
private String taskEndHour;
在Activity中解析數(shù)據(jù):
private void initParseToDoList() {
try {
String response = FileTools.getFileStremFromRaw(activityContext, R.raw.done_gson);
Gson gson = new Gson();
Type type = new TypeToken<BaseResult<XJTaskEntity>>() {
}.getType();
BaseResult<XJTaskEntity> baseResult = gson.fromJson(response, type);
if (baseResult.rltInfo.mGcTaskList != null) {
taskList.addAll(baseResult.rltInfo.mGcTaskList);
}
if (baseResult.rltInfo.mShTaskList != null) {
taskList.addAll(baseResult.rltInfo.mShTaskList);
}
mGsonAdapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 從raw包下讀取數(shù)據(jù)
*
* @param context
* @param rawName R.raw.cqx
* @return
*/
public static String getFileStremFromRaw(Activity context, int rawName) {
try {
InputStreamReader inputReader = new InputStreamReader(context.getResources().openRawResource(rawName));
BufferedReader bufReader = new BufferedReader(inputReader);
String line = "";
String Result = "";
while ((line = bufReader.readLine()) != null)
Result += line;
return Result;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
Gson解析復(fù)雜json的數(shù)據(jù)。
JsonParse:
通過(guò)getAsJsonObject和getAsJsonArray解析成JsonObject和JsonArray。