2018-Gson解析和建立json
概述
本文主要講述瞭如果使用gson來解析含有陣列和物件等比較複雜的json,比如物件中含有物件,物件中有list等。首先會介紹如何在Android Studio中使用外掛方便的將json對映成物件,然後使用gson實現物件和json的相互轉化,最後會詳細介紹如何使用泛型封裝伺服器回撥。
A Java serialization/deserialization library to convert Java Objects into JSON and back
一個將Java物件轉化成json的Java序列化/反序列化庫。
gson主要是用用來解析json為物件和將物件轉化成json。
gradle依賴
compile 'com.google.code.gson:gson:2.8.0'
- 1
1 建立和json對應的物件
這個可以使用Android Studio的外掛,這裡推薦使用GsonFormat,直接在Android Studio的設定,外掛中搜索GsonFormat,安裝之後重啟即可使用。新建一個Java類,點選選單欄的code,Generate…,輸入json字串,在左下角的setting中可以勾選split generate,可以分開生成多個物件。
勾選use serializedName,可以選擇自動新增serializedName註解,這是gson的註解,意思是序列化時的名字,json對映的是這個名字,而不是欄位名,不加這個註解就是對映欄位名。
以下面的json字串為例:
{
"students": [
{
"name": "jadyli",
"gender": "male",
"age": 18
},
{
"name": "Juliet",
"gender": "female",
"age": 20
}
]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
生成的物件是
public class StudentInfo {
private List<Student> students;
public List<Student> getStudents () {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "StudentInfo{" +
"students=" + students.toString() +
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
public class Student {
private String name;
private String gender;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
這樣一個跟json對應得物件就建立好了。
2 使用gson解析json
2.1 解析物件
解析物件使用fromJson(String json, Class classOfT),後面的class需要傳入具體型別。物件裡面有物件或陣列也可以自動解析哦。
String json = "{\"students\":[{\"name\":\"jadyli\",\"gender\":\"male\",\"age\":18},
{\"name\":\"Juliet\",\"gender\":\"female\",\"age\":20}]}";
StudentInfo studentInfo = new Gson().fromJson(json, StudentInfo.class);
System.out.println(studentInfo.toString());
- 1
- 2
- 3
- 4
2.2 解析陣列
直接解析陣列使用fromJson(String json, Type typeOfT)
這個Type,可以使用TypeToken類獲得,比如new TypeToken<List<Student>>() {}.getType()
。
這裡的例子我們要提高json的複雜度,下面這個json表示班級資訊,有兩個班級,A班和B班,每個班級有學生若干。
[
{
"students": [
{
"name": "jadyli",
"gender": "male",
"age": 18
},
{
"name": "Juliet",
"gender": "female",
"age": 20
}
],
"class": "A"
},
{
"students": [
{
"name": "jack",
"gender": "male",
"age": 27
},
{
"name": "Avril",
"gender": "female",
"age": 17
}
],
"class": "B"
}
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
根據json建立相應的物件。我們發現,我們的json中含有Java關鍵字class,這個時候@SerializedName
註解就派上用場了,我們把欄位給為clssX,同時註解裡填上真實的名字class
。Student物件不變。
public class ClassInfo {
@SerializedName("class")
private String classX;
private List<Student> students;
public String getClassX() {
return classX;
}
public void setClassX(String classX) {
this.classX = classX;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "ClassInfo{" +
"classX='" + classX + '\'' +
", students=" + students.toString() +
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
解析上面的json陣列。
List<ClassInfo> classInfoList = new Gson().fromJson("[" +
"{\"students\":[{\"name\":\"jadyli\",\"gender\":\"male\",\"age\":18}," + "{\"name\":\"Juliet\",\"gender\":\"female\",\"age\":20}],\"class\":\"A\"}," +
"{\"students\":[{\"name\":\"jack\",\"gender\":\"male\",\"age\":27},{\"name\":\"Avril\",\"gender\":\"female\",\"age\":17}],\"class\":\"B\"}]",
new TypeToken<List<ClassInfo>>() {
}.getType());
System.out.println(classInfoList.toString());
- 1
- 2
- 3
- 4
- 5
- 6
3 使用gson生成json
一般toJson(Object src)方法就夠用了。
String[] names = {"jadyli", "Juliet"};
String[] genders = {"male", "female"};
int[] ages = {18, 20};
List<Student> students = new ArrayList<>();
for (int i = 0; i < names.length; i++) {
Student student = new Student();
student.setName(names[i]);
student.setGender(genders[i]);
student.setAge(ages[i]);
students.add(student);
}
String jsonStr = new Gson().toJson(students);
System.out.println(jsonStr);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
new Gson().toJson(Object src)輸出的是沒有格式化的json字串,要是想輸出格式化了的,可以使用
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonStr = gson.toJson(students);
- 1
- 2
預設忽略空的欄位,如果不想忽略,可以使用
Gson gson = new GsonBuilder().serializeNulls().create();
String jsonStr = gson.toJson(students);
- 1
- 2
4 特殊用法
不對映特定成員變數
加上@Expose
註解。然後使用的時候用如下語句建立gson物件。
new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
- 1
不對映特定修飾符的成員變數
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
.create();
- 1
- 2
- 3
上面的程式碼會排除static
、transient
、volatile
修飾的成員變數。
指定排除策略
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Foo {
// Field tag only annotation
}
public class SampleObjectForTest {
@Foo private final int annotatedField;
private final String stringField;
private final long longField;
private final Class<?> clazzField;
public SampleObjectForTest() {
annotatedField = 5;
stringField = "someDefaultValue";
longField = 1234;
}
}
public class MyExclusionStrategy implements ExclusionStrategy {
private final Class<?> typeToSkip;
private MyExclusionStrategy(Class<?> typeToSkip) {
this.typeToSkip = typeToSkip;
}
public boolean shouldSkipClass(Class<?> clazz) {
return (clazz == typeToSkip);
}
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Foo.class) != null;
}
}
public static void main(String[] args) {
Gson gson = new GsonBuilder()
.setExclusionStrategies(new MyExclusionStrategy(String.class))
.serializeNulls()
.create();
SampleObjectForTest src = new SampleObjectForTest();
String json = gson.toJson(src);
System.out.println(json);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
4 伺服器json回撥解析例項
這個比較複雜,放到了下一篇部落格