<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Gson全解析(上)-Gson基礎 > gson github地址[google](https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fgoogle)/**[gson](https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fgoogle%2Fgson)** > 本篇文章是基于Gson官方使用指導([Gson User Guide](https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2Fgoogle%2Fgson%2Fblob%2Fmaster%2FUserGuide.md))以及Gson解析的優秀外文(來自[http://www.javacreed.com/](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2F))做出的一個翻譯和歸納。 > 博客原鏈接: > [Gson全解析(上)-Gson基礎](https://www.jianshu.com/p/fc5c9cdf3aab) > [Gson全解析(中)-TypeAdapter的使用](https://www.jianshu.com/p/8cc857583ff4) > [Gson全解析(下)-Gson性能分析](https://www.jianshu.com/p/17a68d4fffbe) * * * # 前言 最近在研究Retrofit中使用的Gson的時候,發現對Gson的一些深層次的概念和使用比較模糊,所以這里做一個知識點的歸納整理。 Gson(又稱Google Gson)是Google公司發布的一個開放源代碼的Java庫,主要用途為序列化Java對象為JSON字符串,或反序列化JSON字符串成Java對象。而**JSON**(JavaScript Object Notation) 是一種輕量級的數據交換格式,易于人閱讀和編寫,同時也易于機器解析和生成,廣泛應用于各種數據的交互中,尤其是服務器與客戶端的交互。 * * * # 基本概念 * Serialization:序列化,使Java對象到Json字符串的過程。 * Deserialization:反序列化,字符串轉換成Java對象。 * JSON數據中的`JsonElement`有下面這四種類型: JsonPrimitive —— 例如一個字符串或整型 JsonObject—— 一個以 JsonElement 名字(類型為 String)作為索引的集合。也就是說可以把 JsonObject 看作值為 JsonElement 的鍵值對集合。 JsonArray—— JsonElement 的集合。注意數組的元素可以是四種類型中的任意一種,或者混合類型都支持。 JsonNull—— 值為null * * * # Gson解決的問題 1. 提供一種像toString()和構造方法的很簡單的機制,來實現Java 對象和Json之間的互相轉換。 2. 允許已經存在的無法改變的對象,轉換成Json,或者Json轉換成已存在的對象。 3. 允許自定義對象的表現形式 4. 支持任意的復雜對象 5. 能夠生成可壓縮和可讀的Json的字符串輸出。 * * * # Gson處理對象的幾個重要點 1 推薦把成員變量都聲明稱private的 2 沒有必要用注解(@Expose 注解)指明某個字段是否會被序列化或者反序列化,所有包含在當前類(包括父類)中的字段都應該默認被序列化或者反序列化 3 如果某個字段被 transient 這個Java關鍵詞修飾,就不會被序列化或者反序列化 4 下面的實現方式能夠正確的處理null 1)當序列化的時候,如果對象的某個字段為null,是不會輸出到Json字符串中的。 2)當反序列化的時候,某個字段在Json字符串中找不到對應的值,就會被賦值為null 5 如果一個字段是 synthetic 的,他會被忽視,也即是不應該被序列化或者反序列化 6 內部類(或者anonymous class(匿名類),或者local class(局部類,可以理解為在方法內部聲明的類))的某個字段和外部類的某個字段一樣的話,就會被忽視,不會被序列化或者反序列化 * * * # Gson中的一些注解 ###### 1 @SerializedName注解 該注解能指定該字段在JSON中對應的字段名稱 ~~~java public class Box { @SerializedName("w") private int width; @SerializedName("h") private int height; @SerializedName("d") private int depth; // Methods removed for brevity } ~~~ 也就是說`{"w":10,"h":20,"d":30}`這個JSON 字符串能夠被解析到上面的width,height和depth字段中。 ##### 2 @Expose注解 該注解能夠指定該字段是否能夠序列化或者反序列化,默認的是都支持(true)。 ~~~tsx public class Account { @Expose(deserialize = false) private String accountNumber; @Expose private String iban; @Expose(serialize = false) private String owner; @Expose(serialize = false, deserialize = false) private String address; private String pin; } ~~~ 需要注意的通過`builder.excludeFieldsWithoutExposeAnnotation()`方法是該注解生效。 ~~~dart final GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); final Gson gson = builder.create(); ~~~ ##### 3 @Since和@Until注解 Since代表“自從”,Until 代表”一直到”。它們都是針對該字段生效的版本。比如說`@Since(1.2)`代表從版本1.2之后才生效,`@Until(0.9)`代表著在0.9版本之前都是生效的。 ~~~kotlin public class SoccerPlayer { private String name; @Since(1.2) private int shirtNumber; @Until(0.9) private String country; private String teamName; // Methods removed for brevity } ~~~ 也就是說我們利用方法`builder.setVersion(1.0)`定義版本1.0,如下: ~~~dart final GsonBuilder builder = new GsonBuilder(); builder.setVersion(1.0); final Gson gson = builder.create(); final SoccerPlayer account = new SoccerPlayer(); account.setName("Albert Attard"); account.setShirtNumber(10); // Since version 1.2 account.setTeamName("Zejtun Corinthians"); account.setCountry("Malta"); // Until version 0.9 final String json = gson.toJson(account); System.out.printf("Serialised (version 1.0)%n %s%n", json); ~~~ 由于`shirtNumber`和`country`作用版本分別是1.2之后,和0.9之前,所以在這里都不會得到序列化,所以輸出結果是: ~~~bash Serialised (version 1.0) {"name":"Albert Attard","teamName":"Zejtun Corinthians"} ~~~ * * * # Gson 序列化 英文Serialize和format都對應序列化,這是一個Java對象到JSON字符串的過程。 接著看一個例子,下面分別是java類和以及我們期望的JSON數據: ~~~tsx public class Book { private String[] authors; private String isbn10; private String isbn13; private String title; //為了代碼簡潔,這里移除getter和setter方法等 } ~~~ ~~~json { "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases", "isbn-10": "032133678X", "isbn-13": "978-0321336781", "authors": [ "Joshua Bloch", "Neal Gafter" ] } ~~~ 你肯定能發現JSON數據中出現了`isbn-10`和`isbn-13`, 我們怎么把字段數據`isbn10`和`isbn13`轉化為JSON數據需要的`isbn-10`和`isbn-13`,Gson當然為我們提供了對應的解決方案 ##### 1 序列化方案1 采用上面提到的`@SerializedName`注解。 ~~~tsx public class Book { private String[] authors; @SerializedName("isbn-10") private String isbn10; @SerializedName("isbn-13") private String isbn13; private String title; //為了代碼簡潔,這里移除getter和setter方法等 } ~~~ ##### 2 序列化方案2 利用`JsonSerializer`類 ~~~java public class BookSerialiser implements JsonSerializer { @Override public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("title", book.getTitle()); jsonObject.addProperty("isbn-10", book.getIsbn10()); jsonObject.addProperty("isbn-13", book.getIsbn13()); final JsonArray jsonAuthorsArray = new JsonArray(); for (final String author : book.getAuthors()) { final JsonPrimitive jsonAuthor = new JsonPrimitive(author); jsonAuthorsArray.add(jsonAuthor); } jsonObject.add("authors", jsonAuthorsArray); return jsonObject; } } ~~~ 下面對序列化過程進行大致的分析: * JsonSerializer是一個接口,我們需要提供自己的實現,來滿足自己的序列化要求。 ~~~java public interface JsonSerializer<T> { /** *Gson 會在解析指定類型T數據的時候觸發當前回調方法進行序列化 * * @param T 需要轉化為Json數據的類型,對應上面的Book * @return 返回T指定的類對應JsonElement */ public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context); } ~~~ * 首先在上面的代碼中,我們需要創建的是一個JsonElement對象,這里對應Book是一個對象,所以創建一個JsonObject類型。 `final JsonObject jsonObject = new JsonObject();` * 然后我們將相應字段里面的數據填充到jsonObject里面。 ~~~css jsonObject.addProperty... jsonObject.add... ~~~ 下面是jsonObject中的添加方法: ![](https://upload-images.jianshu.io/upload_images/1833901-12785eda5dc13763.png?imageMogr2/auto-orient/strip|imageView2/2/w/554/format/webp) * 所以最后返回的還是一個JsonElement 類型,這里對應的是jsonObject。完成了javaBean->JSON數據的轉化。 * 同樣需要配置, ~~~java // Configure GSON final GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser()); gsonBuilder.setPrettyPrinting(); final Gson gson = gsonBuilder.create(); final Book javaPuzzlers = new Book(); javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases"); javaPuzzlers.setIsbn10("032133678X"); javaPuzzlers.setIsbn13("978-0321336781"); javaPuzzlers.setAuthors(new String[] { "Joshua Bloch", "Neal Gafter" }); // Format to JSON final String json = gson.toJson(javaPuzzlers); System.out.println(json); ~~~ ,這里對應的是 `gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser())`方法進行JsonSerializer的配置。在上面例子中,通過調用`gsonBuilder.setPrettyPrinting();`方法還告訴了 Gson 對生成的 JSON 對象進行格式化 * * * # Gson 反序列化 英文parse和deserialise對應反序列化,這是一個字符串轉換成Java對象的過程。 我們同樣采用上面一小節的代碼片段,只不過現在我們需要做的是將: ~~~json { "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases", "isbn-10": "032133678X", "isbn-13": "978-0321336781", "authors": [ "Joshua Bloch", "Neal Gafter" ] } ~~~ 轉化為對應的Book實體類, ##### 1 反序列化方案1 利用`@SerializedName`注解 也就是說我們的實體類Book.java可以這么寫: ~~~tsx public class Book { private String[] authors; @SerializedName("isbn-10") private String isbn10; @SerializedName(value = "isbn-13", alternate = {"isbn13","isbn.13"}) private String isbn13; private String title; //為了代碼簡潔,這里移除getter和setter方法等 } ~~~ ![](https://upload-images.jianshu.io/upload_images/1833901-ab4b02fb8545cade.png?imageMogr2/auto-orient/strip|imageView2/2/w/790/format/webp) > 可以看到這里我們在`@SerializedName`注解使用了一個`value`,`alternate`字段,`value`也就是默認的字段,對序列化和反序列化都有效,`alternate`只有反序列化才有效果。也就是說一般服務器返回給我們JSON數據的時候可能同樣的一個圖片,表示"image","img","icon"等,我們利用`@SerializedName`中的`alternate`字段就能解決這個問題,全部轉化為我們實體類中的圖片字段。 ##### 2 反序列化方案2 我們在序列化的時候使用的是`JsonSerialize`,這里對應使用`JsonDeserializer` 我們將解析到的json數據傳遞給Book的setter方法即可。 ~~~dart public class BookDeserializer implements JsonDeserializer<Book> { @Override public Book deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { final JsonObject jsonObject = json.getAsJsonObject(); final JsonElement jsonTitle = jsonObject.get("title"); final String title = jsonTitle.getAsString(); final String isbn10 = jsonObject.get("isbn-10").getAsString(); final String isbn13 = jsonObject.get("isbn-13").getAsString(); final JsonArray jsonAuthorsArray = jsonObject.get("authors").getAsJsonArray(); final String[] authors = new String[jsonAuthorsArray.size()]; for (int i = 0; i < authors.length; i++) { final JsonElement jsonAuthor = jsonAuthorsArray.get(i); authors[i] = jsonAuthor.getAsString(); } final Book book = new Book(); book.setTitle(title); book.setIsbn10(isbn10); book.setIsbn13(isbn13); book.setAuthors(authors); return book; } } ~~~ 和Gson序列化章節一樣,我們這里接著分析我們是怎么將JSON數據解析(反序列化)為實體類的: * 因為我們可以發現上面的JSON數據是一個`{}`大括號包圍的,也就意味著這是一個Json對象。所以首先我們通過 `final JsonObject jsonObject = json.getAsJsonObject();`將我們的JsonElement轉化為JsonObject * 通過`jsonObject.get("xxx").getAsString()`的形式獲取相應String的值 * 通過`jsonObject.get("xx").getAsJsonArray();`獲取相應的json數組,并遍歷出其中的相應字段值 * 通過setter方法,將獲取到的值設置給Book類。 * 最終返回的是 Book的對象實例。完成了JSON->javaBean的轉化 * 同樣需要配置 * 關于從本地流中讀取Json數據可以使用`InputStreamReader`完成 ~~~kotlin // Configure Gson GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Book.class, new BookDeserializer()); Gson gson = gsonBuilder.create(); // The JSON data try(Reader reader = new InputStreamReader(Main.class.getResourceAsStream("/part1/sample.json"), "UTF-8")){ // Parse JSON to Java Book book = gson.fromJson(reader, Book.class); System.out.println(book); } ~~~ * * * # 參考鏈接 翻譯原文,根據原文做出了較大改動。 1[SIMPLE GSON EXAMPLE](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2Fsimple-gson-example%2F) 2[GSON DESERIALISER EXAMPLE](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2Fgson-deserialiser-example%2F) 3[GSON ANNOTATIONS EXAMPLE](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2Fgson-annotations-example%2F) 4[GSON SERIALISER EXAMPLE](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2Fgson-serialiser-example%2F) 5[GSON TYPEADAPTER EXAMPLE](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2Fgson-typeadapter-example%2F) 6[GSON TYPEADAPTER EXAMPLE SERIALISE LARGE OBJECTS](https://link.jianshu.com/?t=http%3A%2F%2Fwww.javacreed.com%2Fgson-typeadapter-example-serialise-large-objects%2F)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看