一、前言
本篇主要是对Json字符串转换成Java对象的方法进行总结。在介绍前需要对序列化和反序列化这两个名词进行一番解释。
序列化:将Java对象转换成Json字符串。
反序列化:将JSon字符串转换成Java对象。
二、Gson的基本用法
将Json字符串转换为对应的类对象。参见如下范例:
//Json字符串
{
"rst": 0,
"msg": "ok",
"data": {
"cookie": "JSESSIONID=abcntKeuJhop56LGykfdw"
}
}
//对应的Java类
public class JsonRootBean {
private int rst;
private String msg;
private Data data;
public void setRst(int rst) {
this.rst = rst;
}
public int getRst() {
return rst;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setData(Data data) {
this.data = data;
}
public Data getData() {
return data;
}
}
public class Data {
private String cookie;
public void setCookie(String cookie) {
this.cookie = cookie;
}
public String getCookie() {
return cookie;
}
}
//Json字符串转换成Java对象
String json = "{\n" +
" \"rst\": 0,\n" +
" \"msg\": \"ok\",\n" +
" \"data\": {\n" +
" \"cookie\": \"JSESSIONID=abcntKeuJhop56LGykfdw\"\n" +
" }\n" +
"}";
JsonRootBean jsonRootBean = new Gson().fromJson(json, JsonRootBean.class);
备注 :在定义Json对应的Java对象的过程中,只需要保证变量名与Json字符串中变量名相同,类型相同即可,变量的顺序不重要,对不计划进行获取的Json字段信息,Java对象中的变量可以容忍变量的缺失。
三、注解字段的使用
@Expose: Gson字段使用@Expose注解实现字段过滤,该注解必须和com.google.gson.GsonBuilder类配合使用,如果使用com.google.gson.Gson类则不会产生任何作用。
1.@Expose(serialized = true, deserialized = true):序列化和反序列化时都生效,即序列化和反序列都会处理,和不写@Expose注解的含义等同。
2.@Expose(serialized = false, deserialized = false):序列化和反序列化都不生效,即序列化和反序列化都将被忽略。
3.@Expose(serialized = true, deserialized = false):序列化时生效,反序列化时会忽略。
4.@Expose(serialized = false, deserialized = true):反序列化时生效处理,序列化时忽略。
参考代码范例
//Json对应的Java类代码
public class User {
@Expose(serialize = true, deserialize = true)
private String account;
@Expose(serialize = false, deserialize = false)
private String password;
@Expose(serialize = true, deserialize = false)
private String name;
@Expose(serialize = false, deserialize = true)
private int age;
public User() {}
public User(String account, String password, String name, int age) {
this.account = account;
this.password = password;
this.name = name;
this.age = age;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [account=" + account + ", password=" + password + ", name=" + name + ", age=" + age + "]";
}
}
//测试代码
public void test() throws IOException {
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
User user = new User("admin", "123456", "John", 30);
System.out.println(gson.toJson(user));
String userStr = "{\"account\":\"normal\",\"password\":\"xyz123\",\"name\":\"Normal\",\"age\":25}";
User normalUser = gson.fromJson(userStr, User.class);
System.out.println(normalUser);
}
//测试结果输出
{"account":"admin","name":"John"}
User [account=normal, password=null, name=null, age=25]
@SerializeName:重定义属性序列化后的名称,主要是为了保留前端、后台,Android,java不同的命名习惯和规则。参考如下示例:
//Json字符串
{"name":"怪盗kidou","age":24,"email_address":"[email protected]"}
//对应的Java类
public class JavaBean {
private String name;
private String age;
@SerializedName("email_address")
private String emailAddess;
...
}
@SerializedName附带属性alternate的使用,alternate在Gson 2.4版本之后才引入。参考如下:
//当Json字符串中存在email_address、email和emailAddress时都会被序列化成emailAddress
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
四、Gson中的类和方法字段
JsonParse
一个JsonParse解析类,它可以将Json字符串数据分别通过getAsJsonObject和getAsJsonArray解析成jsonObject和JsonArray。参考范例如下:
//Json字符串
{
"muser": [
{
"name": "zhangsan",
"age": "10",
"phone": "11111",
"email": "[email protected]"
},
{
"name": "lisi",
"age": "20",
"phone": "22222",
"email": "[email protected]"
},
...
]
}
//getAsJsonObject
JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
//getAsJsonArray
JsonArray jsonArray = jsonObject.getAsJsonArray("muser");
JsonElement
该类是一个抽象类,代表Json串中的某一个元素,可以是JsonObject, JsonArray和JsonPrimitive等等中的任何一种。
TypeToken
通过new TypeToken< T>(){}.getTpe(); 即可获取Java类T的Type,对T与之对应的Json字符串进行反序列化,可以考虑使用在复杂Json字符串的反序列化中。参考如下示例:
//Json字符串 在代码中表示为jsonStr
{
[
{
"name": "zhangsan",
"age": "10",
"phone": "11111",
"email": "[email protected]"
},
{
"name": "lisi",
"age": "20",
"phone": "22222",
"email": "[email protected]"
},
...
]
}
//Java类
public class JavaBean {
public String name;
public String age;
public String phone;
public String email;
}
//Json转换使用TypeToken
Gson gson = new Gson();
List<JavaBean> javaBeans = gson().fromJson(jsonStr, new TypeToken<List<JavaBean>>() {}.getType());
JsonReader
JsonReader使用起来比较复杂,解析json和xml文件类似,都是根据节点来,使用方式参考如下:
//Json字符串
{
"group": {
"user": {
"name": "张三",
"age": "10",
"phone": "11111",
"email": "[email protected]"
},
"info": {
"address": "北京",
"work": "Android Dev",
"pay": "10K",
"motto": "先定一个小目标,比如我先赚一个亿"
}
}
}
//JsonReader解析使用方法
/**
* 通过JsonReader的方式去解析
*/
private void parseComplexJArrayByReader() throws IOException {
String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_4);
JsonReader reader = new JsonReader(new StringReader(strByJson));
try {
reader.beginObject();
String tagName = reader.nextName();
if (tagName.equals("group")) {
//读group这个节点
readGroup(reader);
}
reader.endObject();
} finally {
reader.close();
}
}
/**
* 读group这个节点
*
* @param reader JsonReader
*/
private void readGroup(JsonReader reader) throws IOException {
reader.beginObject();
while (reader.hasNext()) {
String tagName = reader.nextName();
if (tagName.equals("user")) {
readUser(reader);
} else if (tagName.equals("info")) {
readInfo(reader);
}
}
reader.endObject();
}
/**
* 读用户基本消息 user节点
*
* @param reader JsonReader
*/
private void readUser(JsonReader reader) throws IOException {
reader.beginObject();
while (reader.hasNext()) {
String tag = reader.nextName();
if (tag.equals("name")) {
String name = reader.nextString();
nameText.setText(name);
} else if (tag.equals("age")) {
String age = reader.nextString();
ageText.setText(age);
}
...
else {
reader.skipValue();//忽略
}
}
reader.endObject();
}
/**
* 读用户其他消息 info节点
*
* @param reader JsonReader
*/
private void readInfo(JsonReader reader) throws IOException {
reader.beginObject();
while (reader.hasNext()) {
String tag = reader.nextName();
if (tag.equals("address")) {
String address = reader.nextString();
addressText.setText(address);
} else if (tag.equals("work")) {
String work = reader.nextString();
workText.setText(work);
}
...
else {
reader.skipValue();//忽略
}
}
reader.endObject();
}
参考博客
https://www.jianshu.com/p/e740196225a4
https://blog.csdn.net/Silent_Paladin/article/details/54097942
https://www.cnblogs.com/jianyungsun/p/6647203.html
https://www.cnblogs.com/cynchanpin/p/6743858.html