1. 程式人生 > >Google Gson 使用詳解

Google Gson 使用詳解

Gson Summary

     Java 解析 Json 最常用的類庫有:google 的 Gson阿里巴巴的 FastJson、以及 Jackson。這些都是非常優秀而且常用的庫。

     GSON 是 Google提供的用來在 Java 物件和 JSON 資料之間進行對映的 Java 類庫,可以快速的將一個 Json 字元轉成一個 Java 物件,或者將一個 

Java 物件轉化為 Json 字串。

     gson 在 github 上開源地址:https://github.com/google/gson

二進位制開發包下載

     所有版本下載地址:     gson 二進位制開發包下載地址:https://search.maven.org/artifact/com.google.code.gson/gson/2.8.5/jar

     gson-2.8.4.jar下載gson-2.8.5.jar下載

Maven 依賴

     gson 在 Maven 倉庫地址:https://mvnrepository.com/artifact/com.google.code.gson/gson

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->

<dependency>
  <groupId>com.google.code.gson</groupId>
  <artifactId>gson</artifactId>
  <version>2.8.5</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.4</version>
</dependency>

編碼示例

Gson toJson 與 fromJson 

     Gson 提供了 fromJson() 和 toJson() 兩個直接用於解析和生成的方法,前者實現反序列化,後者實現了序列化。同時每個方法都提供了過載方法.。

     Gson 物件的 toJson 方法可以將基本資料型別、以及 POJO 物件、List、Map 等轉為 json 格式的字串

     Gson 物件的 fromJson 方法做與 toJson 相反的操作,將 json 格式的字串轉為基本資料型別、 POJO 物件、List、Map 等

package com.lct.other;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lct.domain.Person;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2018/11/23 0023.
 */
public class GsonUtils {
    /**
     * json 字串 -> 轉為基本資料型別
     */
    public static void parserJsonToBasicData() {
        Gson gson = new Gson();
        /**
         *  <T> T fromJson(String json, Class<T> classOfT)
         *  json:被解析的 json 字串
         *  classOfT:解析結果的型別,可以是基本型別,也可以是 POJO 物件型別
         */
        int i = gson.fromJson("100", int.class);
        double d = gson.fromJson("100.99", Double.class);
        boolean b = gson.fromJson("true", boolean.class);
        String s = gson.fromJson("愛你", String.class);

        System.out.print(i + "\t" + d + "\t" + b + "\t" + s);
        //輸出:100	100.99	true	愛你
    }


    /**
     * 基本型別 -> 轉為 Json 字串
     */
    public static void parserBasicDataToJson() {
        Gson gson = new Gson();
        /**
         * String toJson(Object src)
         * 將物件轉為 json,如 基本資料、POJO 物件、以及 Map、List 等
         */
        String jsonNumber = gson.toJson(100);
        String jsonDouble = gson.toJson(100.99);
        String jsonBoolean = gson.toJson(false);
        String jsonString = gson.toJson("Tiger");
        System.out.println(jsonNumber + "\t" + jsonDouble + "\t" + jsonBoolean + "\t" + jsonString);
        //輸出:100	100.99	false	"Tiger"
    }


    /**
     * 陣列格式的 Json 字串 - > 轉為 陣列
     */
    public static void parserJsonStrToArray() {
        String jsonArrayStr = "[\"Java\",\"Android\",\"IOS\"]";
        Gson gson = new Gson();
        String[] strings = gson.fromJson(jsonArrayStr, String[].class);
        for (int i = 0; i < strings.length; i++) {
            System.out.print((i + 1) + ":" + strings[i] + "\t");
        }
        //輸出:1:Java	2:Android	3:IOS
    }


    /**
     * 陣列格式的 Json 字串 - > 轉為 List 列表
     */
    public static void parserJsonStrToList() {
        String jsonArray = "[\"Java1\",\"Android2\",\"IOS3\"]";
        Gson gson = new Gson();
        /**
         * 如果解析結果是普通物件,如 單純的 POJO,則可以使用 fromJson(String json, Class<T> classOfT)
         * 如果解析結果是複雜型別,如 List<T> 這種,則應該使用 fromJson(String json, Type typeOfT)
         * json:被轉換的 json 格式的字串
         * typeOfT:解析結果型別
         */
        List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {
        }.getType());

        for (int i = 0; i < stringList.size(); i++) {
            System.out.print((i + 1) + ":" + stringList.get(i) + "\t");
        }
        //輸出:1:Java1	2:Android2	3:IOS3
    }

    /**
     * Java POJO 物件 -> 轉為 json 字串
     */
    public static void parserPOJOToJson() {
        Person person = new Person();
        person.setpId(9527);
        person.setpName("華安");
        person.setBirthday(new Date());
        person.setIsMarry(true);

        Gson gson = new Gson();
        /**
         * String toJson(Object src)
         * 將物件轉為 json,如 基本資料、POJO 物件、以及 Map、List 等
         * 注意:如果 POJO 物件某個屬性的值為 null,則 toJson(Object src) 預設不會對它進行轉化
         * 結果字串中不會出現此屬性
         */
        String jsonUser = gson.toJson(person);
        System.out.println(jsonUser);
        //輸出:{"pId":9527,"pName":"華安","birthday":"Nov 23, 2018 1:50:56 PM","isMarry":true}
    }


    /**
     * Json 字串 -> 轉為 POJO 物件
     */
    public static void parserJsonToPOJO() {
        /**符合 json 格式的字串*/
        String personJson = "{\"pId\":9527,\"pName\":\"華安\",\"birthday\":\"Nov 23, 2018 1:50:56 PM\",\"isMarry\":true}";

        Gson gson = new Gson();
        /**
         *  <T> T fromJson(String json, Class<T> classOfT)
         *  json:被解析的 json 字串
         *  classOfT:解析結果的型別,可以是基本型別,也可以是 POJO 物件型別,gson 會自動轉換
         */
        Person person = gson.fromJson(personJson, Person.class);
        System.out.println(person);
        //輸出:Person{birthday=Fri Nov 23 13:50:56 CST 2018, pId=null, pName='華安', isMarry=true}

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String personBirthday = dateFormat.format(person.getBirthday());
        System.out.println("使用者生日:" + personBirthday);
        //輸出:使用者生日:2018-11-23 13:50:56
        //可見日期字串也能完美轉換
    }

    /**
     * List 集合 -> 轉為 json 字串
     * list 會被解析成 Json 陣列,List 中的元素被解析成 json
     */
    public static void parserPOJOListToJson() {
        Person person = new Person();
        person.setpId(9527);
        person.setpName("華安");
        person.setBirthday(new Date());
        person.setIsMarry(true);

        Person person2 = new Person();
        person2.setpId(8866);
        person2.setpName("寧王");

        List<Person> personList = new ArrayList<>();
        personList.add(person);
        personList.add(person2);
        Gson gson = new Gson();
        /**
         * String toJson(Object src)
         * 將物件轉為 json,如 基本資料、POJO 物件、以及 Map、List 等
         * 注意:如果 POJO 物件某個屬性的值為 null,則 toJson(Object src) 預設不會對它進行轉化
         * 結果字串中不會出現此屬性
         */
        String personListJson = gson.toJson(personList);
        System.out.println(personListJson);
        //輸出:[{"pId":9527,"pName":"華安","birthday":"Nov 23, 2018 2:05:58 PM","isMarry":true},{"pId":8866,"pName":"寧王","isMarry":false}]
    }
}

JsonObject、JsonArray、JsonParser

     JsonObject 表示 json 物件、JsonArray 表示 json 物件陣列、JsonParser 表示 json 解析,將 json 格式的字串解析為 JsonObject、JsonArray 物件。

package com.lct.other;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * Created by Administrator on 2018/11/23 0023.
 */
public class JsonUtils {

    /**
     * Json 格式字串 -> 解析為 JSON 物件
     */
    public static void parserJsonStrToJsonObj() {
        String jsonStr = "{\"pId\":9527,\"pName\":\"華安\",\"birthday\":\"Nov 23, 2018 1:50:56 PM\",\"isMarry\":true}";

        JsonParser jsonParser = new JsonParser();
        /**JsonElement parse(String json)
         * 如果被解析的字串不符合 json 格式,則丟擲異常*/
        JsonObject jsonObject = jsonParser.parse(jsonStr).getAsJsonObject();

        /**JsonElement get(String memberName)
         * 注意:如果 get 的 key 不存在,則返回 null,如果不加判斷而進行取值的話,會拋:java.lang.NullPointerException
         * */
        Integer pId = jsonObject.get("pId").getAsInt();
        String pName = jsonObject.get("pName").getAsString();

        System.out.println(jsonObject);
        //輸出:{"pId":9527,"pName":"華安","birthday":"Nov 23, 2018 1:50:56 PM","isMarry":true}
        System.out.println(pId + "\t" + pName);
        //輸出:9527	華安
    }

    /**
     * Json 陣列字串 -> 解析為 JSON 陣列物件
     */
    public static void parserJsonStrToJsonArray() {
        String jsonArrayStr = "[{\"pId\":9527,\"pName\":\"華安\",\"isMarry\":true},{\"pId\":8866,\"pName\":\"寧王\",\"isMarry\":false}]";
        JsonParser jsonParser = new JsonParser();
        JsonArray jsonArray = jsonParser.parse(jsonArrayStr).getAsJsonArray();

        for (int i = 0; i < jsonArray.size(); i++) {
            JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
            System.out.println((i + 1) + ":" + jsonObject + "\t\t" + jsonObject.get("pName").getAsString());
        }
        //輸出:1:{"pId":9527,"pName":"華安","isMarry":true}		華安
        //輸出:2:{"pId":8866,"pName":"寧王","isMarry":false}		寧王
    }


    /**
     * 手動 建立 JSON物件 並新增基本型別屬性
     */
    public static void createJsonObj() {
        /**
         * JsonObject 新增基本型別屬性使用 addProperty(String property, Number value)、 addProperty(String property, String value) 等
         * JsonObject 新增複雜型別屬性使用 add(String property, JsonElement value)
         * JsonObject 與 JsonArray 都是 JsonElement 類的子類
         * 提示:如果新增的 key 已經存在,則後面的會覆蓋前面的
         */
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("pId", 9527);
        jsonObject.addProperty("pName", "華安");
        jsonObject.addProperty("isMarry", true);

        /**
         * JsonObject 取值使用 JsonElement get(String memberName),根據 JsonElement 可以獲取任意型別
         * JsonObject 可以直接獲取 JsonArray:JsonArray getAsJsonArray(String memberName)
         * JsonObject 可以直接獲取 JsonObject:JsonObject getAsJsonObject(String memberName)
         */
        System.out.println(jsonObject + "\t" + jsonObject.get("pName").getAsString());
        //輸出:{"pId":9527,"pName":"華安","isMarry":true}	華安
    }


    /**
     * 建立 JSON 陣列
     */
    public static void createJsonArray() {
        String json1 = "{\"pId\":9527,\"pName\":\"華安\",\"isMarry\":true}";
        String json2 = "{\"pId\":1200,\"pName\":\"安祿山\",\"isMarry\":false}";

        JsonObject jsonObject1 = new JsonParser().parse(json1).getAsJsonObject();
        JsonObject jsonObject2 = new JsonParser().parse(json2).getAsJsonObject();

        JsonArray jsonArray = new JsonArray();
        jsonArray.add(jsonObject1);
        jsonArray.add(jsonObject2);

        System.out.println(jsonArray);
        //輸出:[{"pId":9527,"pName":"華安","isMarry":true},{"pId":1200,"pName":"安祿山","isMarry":false}]
    }


    /**
     * 刪除 JsonObject 的某個屬性
     */
    public static void delJsonObjproperty() {
        String json = "{\"pId\":9527,\"pName\":\"華安\",\"isMarry\":true}";
        JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
        System.out.println("刪除前:" + jsonObject);
        //輸出:刪除前:{"pId":9527,"pName":"華安","isMarry":true}
        /**
         * JsonElement remove(String property)
         * 用於刪除 JsonObject 的屬性,返回被刪除的屬性的值,原 JsonObject 會改變
         * 與get取值同理,如果 remove 的屬性值不存在,則返回 null
         */
        String delProperty = jsonObject.remove("pName").getAsString();

        System.out.println("刪除 " + delProperty + " 後:" + jsonObject);
        //輸出:刪除 華安 後:{"pId":9527,"isMarry":true}
    }


    /**
     * 修改 JsonObject 屬性,與新增一樣使用 addProperty,當 key 已經存在時,會覆蓋舊值
     */
    public static void updateJsonObjproperty() {
        String json = "{\"currentOnlineNumber\":\"101\",\"name\":\"汪茂雄\"}";
        JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
        System.out.println("修改前:" + jsonObject);

        jsonObject.addProperty("name", "趙麗穎");
        System.out.println("修改後:" + jsonObject);
    }

    /**
     * 獲取 JsonObject 屬性值
     */
    public static void getJsonObjproperty() {
        String json = "{\"pId\":9527,\"pName\":\"華安\",\"Dog\":{\"dName\":\"小黃\",\"color\":\"yellow\"}}";
        JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
        System.out.println("操作物件:" + jsonObject);

        /**
         * JsonElement get(String memberName):如果 memberName 不存在,則返回 null
         * 所以除非應用中明確知道key存在,否則應該加以判斷
         */
        Integer pId = jsonObject.get("pId").getAsInt();
        System.out.println("pId=" + pId);

        /** boolean has(String memberName)
         * 判斷 JsonObject 中是否存在某個 key*/
        if (!jsonObject.has("name")) {
            System.out.println("name 屬性不存在...");
        }

        /**
         * JsonObject 取值使用 JsonElement get(String memberName),根據 JsonElement 可以獲取任意型別
         * JsonObject 可以直接獲取 JsonArray:JsonArray getAsJsonArray(String memberName)
         * JsonObject 可以直接獲取 JsonObject:JsonObject getAsJsonObject(String memberName)
         */
        JsonObject dogJson = jsonObject.getAsJsonObject("Dog");
        System.out.println(dogJson);
    }

    /**
     * 實際應用中,如果業務比較複雜,則通常都會巢狀 json,如下所示:
     * [{"pId":110,"pName":"華安","Dog":{"dName":"小黃","color":"yellow"}},{"pId":120,"pName":"安祿山","Dog":{"dName":"阿毛","color":"red"}}]
     */
    public static void complexParsen() {
        /**兩隻小狗 json 字串*/
        String dog1JsonStr = "{\"dName\":\"小黃\",\"color\":\"yellow\"}";
        String dog2JsonStr = "{\"dName\":\"阿毛\",\"color\":\"red\"}";

        /**將 json 字串解析為 JsonObject 物件*/
        JsonObject dog1Json = new JsonParser().parse(dog1JsonStr).getAsJsonObject();
        JsonObject dog2Json = new JsonParser().parse(dog2JsonStr).getAsJsonObject();

        /**建立兩個使用者的 JsonObject 物件*/
        JsonObject user1Json = new JsonObject();
        JsonObject user2Json = new JsonObject();

        /**新增普通值*/
        user1Json.addProperty("pId", 110);
        user1Json.addProperty("pName", "華安");
        /**新增JsonObject物件
         * 注意:新增的物件,而不應該是符合 json 格式的字串*/
        user1Json.add("Dog", dog1Json);

        user2Json.addProperty("pId", 120);
        user2Json.addProperty("pName", "阿毛");
        user2Json.add("Dog", dog2Json);

        /**建立 JsonArray 用於存放 JsonObject
         * 同樣新增的應該是物件,而不應該是符合格式的字串*/
        JsonArray jsonArray = new JsonArray();
        jsonArray.add(user1Json);
        jsonArray.add(user2Json);

        System.out.println(jsonArray);
        //輸出:[{"pId":110,"pName":"華安","Dog":{"dName":"小黃","color":"yellow"}},{"pId":120,"pName":"阿毛","Dog":{"dName":"阿毛","color":"red"}}]
    }

    public static void main(String[] args) {
        getJsonObjproperty();
    }
}

欄位值為 null 時是否序列化

     Gson 在 toJson 的時候,預設是不會對屬性值為 null 的欄位進行序列化的,即結果中不會包含它,可以使用 GsonBuild  的 serializeNulls 方法構建 Gson,這樣就會對屬性值為 null 的欄位進行序列化。

     實際應用中,是否對屬性值為 null 的欄位進行序列化,根據需求定即可,建議進行序列化。

/**
     * 物件中為 null 的欄位,是否實行序列化,為了降低 bug,應該保持一致
     * 實際應用中,前後臺數據互動,系統之間資料傳遞時,如果接收端在獲取某個值的時候不存在,而傳送端以為自己以及傳送了,
     * 其實就是欄位值可能為 null,傳送端傳送的時候,導致沒有進行序列化
     */
    public static void parserPOJOToJsonContainNull() {
        /**
         * Person 實體一共4個欄位:Integer pId、String pName、Date birthday、Boolean isMarry
         * 現在它的屬性全部不進行賦值
         */
        Person person = new Person();

        /** 不對屬性值為 null 的欄位進行序列化,轉換結果會為空*/
        String personStr = new Gson().toJson(person);

        /** 對屬性值為 null 的欄位進行序列化*/
        String personStrFinal = new GsonBuilder().serializeNulls().create().toJson(person);

        System.out.println(personStr);
        //輸出:{}
        System.out.println(personStrFinal);
        //輸出:{"pId":null,"pName":null,"birthday":null,"isMarry":null}

        /** 對於欄位值為 null 的字串,解析的時候也需要注意
         * JsonElement get(String memberName) 的時候返回的就是 null
         */
        JsonObject jsonObject = new JsonParser().parse(personStrFinal).getAsJsonObject();
        System.out.println(jsonObject.get("pName"));//輸出:null

        /**判斷元素是否為 null*/
        System.out.println(jsonObject.get("pName").isJsonNull());
        //輸出:true
    }