GSON - JSON的拓展

GSON使用概述

GSON彌補了JSON的許多不足的地方,在實際應用中更加適用於Java開發。在這裏,咱們主要講解的是利用GSON來操做java對象和json數據之間的相互轉換,包括了常見的對象序列化和反序列化的知識。javascript

1、前言

由於json有2種類型:前端

  • 一種是對象,object -> {key:value,key:value,...}
  • 另外一種是數組,array -> [value,value,...]

因此針對這兩種類型,來展開對json數據的操做。java

GSON在解析json的時候,大致上有2種類型,一種是直接在內存中生成object或array,經過手工指定key來獲取值;另外一種是藉助javabean來進行映射獲取值。ajax

2、對 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);

1. json 是對象類型

1.1 基本案列

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的規範和常理。

1.2 字段名並不一致怎麼辦?

若是前端傳過來的json 數據的key和咱們java類的字段不一致,就須要咱們在java類中手工進行指定。

@SerializedName() 註解

好比對於上面的json 數據,salary 改爲money ,咱們獲得的java對象中,salary 就會變成默認值:0。

所以,咱們要使用註解:

@SerializedName("money")
private String salary;

@SerializedName({"money", "salary"})  // 能夠有多個備選值
private String salary;
1.3 如何限定某個字段不參加序列化或反序列化?

@Expose()註解

若是想要讓java類的某些字段不參加序列化或反序列化,能夠顯示來設置。如:

@Expose(serialize=false,deserialize=false)
private String name;

上面的name 字段將不參加序列化及反序列化。

1.4 複合的對象怎麼處理?

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類。

2. json 是數組類型

1.1 基本案例:

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);
1.2 我想用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
}
1.1 data爲對象的json1:
{
  "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);
1.2 data爲數值的json2:
{
  "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);

4、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中的默認值。

1.1 要生成對象形式的json 數據

  • 第一種方法是上面的,直接使用java類對象
  • 還可使用生成map對象,進行序列化

1.2 要生成數組形式的json 數據

  • 第一種,使用String[] 字符串數組來生成
  • 還可使用List對象來序列化
  • 還可使用Set對象來序列化

對於序列化的要求,更多的狀況會使用註解來選擇須要/不須要進行序列化的字段。

相關文章
相關標籤/搜索