项目中一直使用的原生解析JSONObject.
参考链接https://www.jianshu.com/p/e740196225a4#
基于Gson V2.8.5
序列化: 把Java对象转换为字节序列的过程。 eg:toJson(对象)
反序列化:把字节序列恢复为Java对象的过程。eg:fromJson("字节序列",对象)
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 {}
基本数据类型的生成、
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;
...
如果此时按照以下解析,哪怕try catch也拦截不到。
/**
* 从raw包下读取数据
* @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 "";
}
解析上面的报文。
private void parseJsonReponse() {
String response = FileTools.getFileStremFromRaw(this, R.raw.test);
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = jsonParser.parse(response).getAsJsonObject();
try {
//因为对应的为Object,所以这样的解析就会异常崩溃,并且拦截无用。
JsonArray jsonArray = jsonParser.parse(response).getAsJsonArray();
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
String msg=jsonObject.get("msg").getAsString();
}
错误日志如下:
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)
然后实际开发中,后台返回的json格式可能跟我们要的不一致,如果线上的因为后台返回的数据格式而崩溃,哪怕最终查出原因是后台的问题,最终客户端还是得背锅,谁叫没有做容错处理呢。
如果服务端返回的为正确的数据解析方式:
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的生成
将对象转换为字节序列的过程。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
将字节系列转为为对象的过程。fromJson
UserEntity userEntity = gson.fromJson(jsonObject, UserEntity.class);
List<UserEntity> list = gson.fromJson(jsonArray, new TypeToken<List<UserEntity>>() {
}.getType());
数组
String[] strings = gson.fromJson(jsonArray, String[].class);
List
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
@Expose、@SerializeName注解
json解析的字段(key)的名称和类型是一一对应的,当客户端和后台使用的语言不同,二者语言命名规范不同,命名规则常常不统一的情况下,使用@Expose和@SerializeName注解。
@Expose注解:区分实体中序列号的属性,包含两个属性,deserialize(反序列化)和serialize(序列化),默认为true。使用@Expose进行序列化,如果不想被序列化也可以使用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注解:属性重命名
//使用这样的方式创建gson对象。
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;
如果存在一个key多个写法,则可以选择@SerializeName的alternate别名的选择,根据以上代码可知为一个字符串数组。
借用例子
{"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
链接:https://www.jianshu.com/p/e740196225a4#
所以处理办法是:
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
多个情况同时存在时:
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
链接:https://www.jianshu.com/p/e740196225a4#
补充demo
。
如上图可以看到该json格式为外层JsonObject,里面有个key为rltInfo的JsonObject,rltInfo里面存在两个JsonArray的数组list.可以简易封装一下解析:
//基类
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客户端命名规则,shTaskList为服务端返回来的json的key
@SerializedName("shTaskList")
public List<T> mShTaskList;
}
/**
* created by cheng.qx on 2018/8/20 17:10
*/
public class XJTaskEntity {
/**
* 任务ID
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 所属用户ID
*/
private String personId;
/**
* 所属用户名称
*/
private String personName;
/**
* 门店ID
*/
private String storeId;
/**
* 门店名称
*/
@SerializedName("orgName")
private String storeName;
/**
* 区域ID
*/
private String areaId;
/**
* 区域名称
*/
private String areaName;
/**
* 任务开始时间-天
*/
@SerializedName(value ="beginTimeStr",alternate={"submitTimeStr"})
private String taskBeginDay;
/**
* 任务开始时间-时分秒
*/
private String taskBeginHour;
/**
* 任务结束时间-天
*/
@SerializedName("endTimeStr")
private String taskEndDay;
/**
* 任务结束时间-时分秒
*/
private String taskEndHour;
在Activity中解析数据:
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包下读取数据
*
* @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解析复杂json的数据。
JsonParse:
通过getAsJsonObject和getAsJsonArray解析成JsonObject和JsonArray。