GSON彌補了JSON的許多不足的地方,在實際應用中更加適用於Java開發。在這裏,咱們主要講解的是利用GSON來操做java對象和json數據之間的相互轉換,包括了常見的對象序列化和反序列化的知識。javascript
由於json有2種類型:前端
object
-> {key:value,key:value,...}
。array
-> [value,value,...]
。因此針對這兩種類型,來展開對json數據的操做。java
GSON在解析json的時候,大致上有2種類型,一種是直接在內存中生成object或array,經過手工指定key來獲取值;另外一種是藉助javabean來進行映射獲取值。ajax
json
數據進行反序列化,獲得java
對象java
類,直接解析json
數據json
是對象類型當ajax傳過來的json數據屬於對象時,不論這個對象簡單仍是複雜,均可以輕鬆地把它們給解析出來。json
ajax傳過來的json數據(是對象形式):數組
var data_json = { "sex": '男', "hobby":["baskte","tennis"], "introduce": { "name":"tom", "age":23 } }; data: JSON.stringify(data_json),
GSON解析:app
BufferedReader reader = request.getReader(); // 讀取json數據 StringBuffer buffer = new StringBuffer(); String s; while ((s = reader.readLine()) != null) { buffer.append(s); } String json = buffer.toString(); System.out.println("json:" + json); // json解析器,解析json數據 JsonParser parser = new JsonParser(); JsonElement element = parser.parse(json); // json屬於對象類型時 if (element.isJsonObject()) { JsonObject object = element.getAsJsonObject(); // 轉化爲對象 // 1. value爲string時,取出string String sex = object.get("sex").getAsString(); System.out.println("sex:" + sex); // 2. value爲array時,取出array JsonArray hobbies = object.getAsJsonArray("hobby"); // for (int i = 0; i < hobbies.size(); i++) { String hobby = hobbies.get(i).getAsString(); System.out.println("hobby:" + hobby); } // 3. value爲object時,取出object JsonObject introduce = object.getAsJsonObject("introduce"); String name = introduce.get("name").getAsString(); int age = introduce.get("age").getAsInt(); System.out.println("name:" + name+";age:" + age); }
解讀:ui
很明顯,對於傳過來的對象類型的json數據,使用GSON是很方便進行解析的,在獲得了json數據對應的JsonObject
對象以後,咱們就能夠很簡單地進行操做了。這種方法是直接獲取json中的值,而沒有進行java對象的還原(簡單狀況下,沒有必要生成相應的javabean)。code
json
是數組類型ajax傳過來的json數據(是數組形式):對象
var data_json = [ "cake", 2, {"brother":"tom","sister":"lucy"}, ["red","orange"] ]; data: JSON.stringify(data_json),
GSON解析:
BufferedReader reader = request.getReader(); StringBuffer buffer = new StringBuffer(); String s; while ((s = reader.readLine()) != null) { buffer.append(s); } String json = buffer.toString(); System.out.println("json:"+json); // json解析器,解析json數據 JsonParser parser = new JsonParser(); JsonElement element = parser.parse(json); // json屬於數組類型 if (element.isJsonArray()) { JsonArray array = element.getAsJsonArray(); // 1. value爲string時,取出string String array_1 = array.get(0).getAsString(); System.out.println("array_1:"+array_1); // 2. value爲int時,取出int int array_2 = array.get(1).getAsInt(); System.out.println("array_2:"+array_2); // 3. value爲object時,取出object JsonObject array_3 = array.get(2).getAsJsonObject(); String brother = array_3.get("brother").getAsString(); String sister = array_3.get("sister").getAsString(); System.out.println("brother:"+brother+";sister:"+sister); // 4. value爲array時,取出array JsonArray array_4 = array.get(3).getAsJsonArray(); for (int i = 0; i < array_4.size(); i++) { System.out.println(array_4.get(i).getAsString()); } }
解讀:
當json是數組類型的時候,使用GSON操做和上一小節幾乎差很少,只不過是第一步生成的json對象是數組而已。上面2種方式解析json十分簡單,在平常使用中足夠了。
可是對於有規律的json數據,好比每每是能夠映射成一個javabean對象,那麼咱們就沒有必要一個個手工取值了,咱們能夠藉助javabean配合GSON來更加快速地解析json數據。
java
類,生成對應java
對象來解析數據詳細的前端json
數據,能夠看前面的反例,如下只是使用直接的json
數據進行說明。
生成對於的java對象以後,就能夠經過getter方法來獲取相應的數據了。
通用代碼:
在這個方法裏,藉助json數據來生成java對象的代碼都是一致的:
Gson gson = new Gson(); BeanType bean = gson.fronJson(jsonData, BeanType.class);
json
是對象類型json
數據
{"name":"tom","salary":2999}
java類
public class MyEntry { private String name; private int age; public String address; public int salary; // getter、setter、toString }
java
代碼
String json1 = "{\"name\":\"tom\",\"salary\":2999}"; Gson gson1 = new Gson(); MyEntry entry1 = gson1.fromJson(json1, MyEntry.class); System.out.println(entry1.toString()); // name:tom,age:0,address:null,salary:2999
解讀
能夠看出,對於不完整的json
數據,在咱們映射了相應的java
類以後,轉化獲得的java對象,未賦值的字段都是默認值。這就符合java的規範和常理。
若是前端傳過來的json
數據的key和咱們java類的字段不一致,就須要咱們在java類中手工進行指定。
@SerializedName()
註解
好比對於上面的json
數據,salary
改爲money
,咱們獲得的java對象中,salary
就會變成默認值:0。
所以,咱們要使用註解:
@SerializedName("money") private String salary; @SerializedName({"money", "salary"}) // 能夠有多個備選值 private String salary;
@Expose()註解
若是想要讓java類的某些字段不參加序列化或反序列化,能夠顯示來設置。如:
@Expose(serialize=false,deserialize=false) private String name;
上面的name
字段將不參加序列化及反序列化。
當json
數據是對象形式時,常見的value
會是一個數組或對象。如:
{ "name": "tom", "age": 0, "money": 2999, "hobbies": [ "basket", "tennis" ], "collections": { "2": "paint", "3": "mouse" } }
觸類旁通,value
是數組時(hobbies),對應在java類中也是數組;value
是對象時,對應在java類中就是map(k-v對)了。
所以,咱們能夠很容易獲得對應的java類:
private List<String> hobbies; private Map<Integer, String> collections;
解讀: 可知,再複雜的json
數據,咱們也能夠構造出對應的java類。
json
是數組類型json數據
["apple", "banana", "pear"]
顯然,數組在java中對應的也是數組。
java代碼
String json2 = "[\"apple\", \"pear\", \"banana\"]"; Gson gson2 = new Gson(); // 傳入的java類型是String[].class String[] fruits = gson2.fromJson(json2, String[].class);
List
數組對於上面這種簡單的數組形式的json數據,咱們還能夠反序列化爲List類型的數組。由於List進行增刪改都比較方便。
這裏就要使用泛型了,具體的泛型講解,會在下面進行說明。
String json2 = "[\"apple\", \"pear\", \"banana\"]"; Gson gson2 = new Gson(); List<String> fruitList = gson2.fromJson(json2, new TypeToken<List<String>>(){}.getType());
有的時候,傳過來的json數據在格式上是很相近的,只不過某個字段的value不固定,若是爲今生成多個類似的java類就十分多餘了。
如:前端傳過來的json數據主要是2類:
{"code":"0","message":"success","data":{}}
{"code":"0","message":"success","data":[]}
對於字段data
,有時候是對象,有時候是數組。
這裏,咱們將使用Result<T>
來映射json
數據,使用MyEntry
類來映射json
數據的data
部分。這意味着,對於不一樣的json數據,咱們將再也不生成多個java類,而是動態生成所需的java對象。
result對象
public class Result<T>{ public int code; public String message; public T data; // getter、setter }
{ "code": 0, "message": "success", "data": [ { "name": "tom", "age": 32, "address": "street one", "salary": 4999 }, { "name": "tom", "age": 32, "address": "street one", "salary": 4999 } ] }
java代碼
String typeJson1 = "{\n" + " \"code\":0,\n" + " \"message\":\"success\",\n" + " \"data\":{\n" + " \"name\":\"tom\",\n" + " \"age\":32,\n" + " \"address\":\"street one\",\n" + " \"salary\":4999\n" + " }\n" + "}"; Gson typeGson1 = new Gson(); // 動態生成所需的java類的類型 Type type1 = new TypeToken<Result<MyEntry>>(){}.getType(); // 動態生成java對象 Result<MyEntry> result1 = typeGson1.fromJson(typeJson1, type1); System.out.println(result1);
{ "code": 0, "message": "success", "data": [ { "name": "tom", "age": 32, "address": "street one", "salary": 4999 }, { "name": "lucy", "age": 24, "address": "street three", "salary": 2333 } ] }
java代碼
String typeJson2 = "{\n" + " \"code\": 0,\n" + " \"message\": \"success\",\n" + " \"data\": [\n" + " {\n" + " \"name\": \"tom\",\n" + " \"age\": 32,\n" + " \"address\": \"street one\",\n" + " \"salary\": 4999\n" + " },\n" + " {\n" + " \"name\": \"lucy\",\n" + " \"age\": 24,\n" + " \"address\": \"street three\",\n" + " \"salary\": 2333\n" + " }\n" + " ]\n" + "}"; Gson typeGson2 = new Gson(); // 再次動態生成java類型 Type type2 = new TypeToken<Result<List<MyEntry>>>(){}.getType(); // 再次動態生成java對象 Result<List<MyEntry>> result2 = typeGson2.fromJson(typeJson2, type2); System.out.println(result2);
java
對象序列化爲json
數據這一部分,主要是講解如何將一個java對象序列化爲json數據,也會涉及到如何組裝這個java對象。
java
類對象,序列化爲json
數據咱們能夠直接把java對象給序列化爲json數據。對於未設置的屬性,會採起默認值;可是若是默認是null的話,該屬性就不會被序列化。
java類,咱們仍然採用的是MyEntry
類。
MyEntry entry2 = new MyEntry(); entry2.setName("tom"); entry2.setSalary(2999); List<String> hobbies = new ArrayList<>(); hobbies.add("basket"); hobbies.add("tennis"); entry2.setHobbies(hobbies); Map<Integer, String> collections = new HashMap<>(); collections.put(2, "paint"); collections.put(3, "mouse"); entry2.setCollections(collections); Gson gson2 = new Gson(); String json2 = gson2.toJson(entry2); System.out.println(json2); // {"name":"tom","age":0,"money":2999,"hobbies":["basket","tennis"],"collections":{"2":"paint","3":"mouse"}}
對於非值屬性,即引用屬性,如hobbies、collections,若是沒有設置值的話,在序列化後的json數據中,是不會出現的。而若是是值屬性的話,沒有設置值的狀況下,在json數據中會是使用java中的默認值。
json
數據json
數據String[]
字符串數組來生成對於序列化的要求,更多的狀況會使用註解來選擇須要/不須要進行序列化的字段。