Gson——嵌套對象的映射

原文鏈接:Gson — Mapping of Nested Objects

作者:Norman Peitek

翻譯:簽到錢就到

在Gson博客文章中,我們研究了基本的功能。這篇文章,我們要關(guān)注一些更實際的數(shù)據(jù),并且研究嵌套對象。你會學(xué)會如何簡單地處理那些包含復(fù)雜數(shù)據(jù)的對象。

這只是我們Gson系列中的一篇。如果你對其他主題感興趣,可以看一下下面的大綱:

Gson系列概覽

  1. 用java-JSON實現(xiàn)序列化合反序列化
  2. 嵌套對象的映射
  3. Mapping of Arrays and Lists of Objects
  4. Mapping of Maps
  5. Mapping of Sets
  6. Mapping of Null Values
  7. Gson Model Annotations — How to Ignore Fields with @Expose
  8. Gson Model Annotations — How to Change the Naming of Fields with @SerializedName
  9. Gson Builder — Basics & Naming Policies
  10. Gson Builder — Force Serialization of null Values
  11. Gson Builder — Exclusion Strategies
  12. Gson Builder — Relax Gson with Lenient
  13. Gson Builder — Special Values of Floats & Doubles
  14. Gson Builder — Model Versioning
  15. Gson Builder — Formatting of Dates & Custom Date/Time Mapping
  16. Gson Builder — Pretty Printing
  17. Gson Builder — HTML Escaping

嵌套對象的序列化

我們喜歡用實際的例子來演示功能,所以,讓我們擴(kuò)展UserSimple模型。在之前的文章中,user模型只有一些標(biāo)準(zhǔn)的java類型:

public class UserSimple {  
    String name;
    String email;
    boolean isDeveloper;
    int age;
}

現(xiàn)在我們的user也有了一個家庭地址,這個家庭地址也有自己的模型類UserAddress

public class UserNested {  
    String name;
    String email;
    boolean isDeveloper;
    int age;

    // new, see below!
    UserAddress userAddress;
}

public class UserAddress {  
    String street;
    String houseNumber;
    String city;
    String country;
}

換句話說,user現(xiàn)在是用一個UserNested模型表示,其中有一個額外的一對一的地址對象。地址是在UserAddress模型中表示的。

在java中,這兩個模型能夠通過類清晰地區(qū)分,并且我們通過UserAddress userAddress字段保持引用。然而,在JSON里,沒有類或引用。只有嵌套nest)用戶地址到用戶對象中。基本地,在JSON里我們只要用{}在字段名字后創(chuàng)建一個新的對象:

{
    "age": 26,
    "email": "norman@futurestud.io",
    "isDeveloper": true,
    "name": "Norman",

    "userAddress": {
        "city": "Magdeburg",
        "country": "Germany",
        "houseNumber": "42A",
        "street": "Main Street"
    }
}

不同于其他屬性(age,email,...),新的userAddress沒有直接的值。而是有一些包含在{}內(nèi)的子值。很重要的一點,需要你理解字段名字后面有括號的就是表明這是一個嵌套對象。

太多的理論。是時候見識一下Gson從UserNested對象中創(chuàng)建了什么。你可能認(rèn)識這個模式,Gson不需要任何配置。它會自動根據(jù)傳進(jìn)的類推斷出數(shù)據(jù)結(jié)構(gòu):

UserAddress userAddress = new UserAddress(  
    "Main Street", 
    "42A", 
    "Magdeburg", 
    "Germany"
);

UserNested userObject = new UserNested(  
    "Norman", 
    "norman@futurestud.io", 
    26, 
    true, 
    userAddress
);

Gson gson = new Gson();  
String userWithAddressJson = gson.toJson(userObject); 

你應(yīng)該會很好奇,字符串userWithAddressJson的值是什么樣子的:

{
    "age": 26,
    "email": "norman@futurestud.io",
    "isDeveloper": true,
    "name": "Norman",

    "userAddress": {
        "city": "Magdeburg",
        "country": "Germany",
        "houseNumber": "42A",
        "street": "Main Street"
    }
}

細(xì)心的你很容易發(fā)現(xiàn),雖然Gson又一次按照字母順序存儲了字段,但結(jié)果正是我們期望的。Gson正確地創(chuàng)建了嵌套userAddressJSON對象。當(dāng)然,我們可以為用戶的薪水方法或工作地址增加更多的嵌套對象。甚至嵌套對象里也能有嵌套對象!

在下一節(jié)中,我們會研究另一個方向。如何反序列化復(fù)雜的嵌套JSON到Java對象呢?

嵌套對象的反序列化

上一節(jié)中,我們假設(shè)模型已經(jīng)有了,并且我們只要創(chuàng)建一個匹配的JSON。特別是對于在真實世界里的開發(fā)者,經(jīng)常是相反的。API接口正在返回一些JSON數(shù)據(jù),我們需要為那些數(shù)據(jù)創(chuàng)建模型類。

如果你已經(jīng)讀了第一篇文章的一些內(nèi)容,你已經(jīng)感覺到如何創(chuàng)建一個模型類。防止你覺得無聊,所以我們將從user的例子轉(zhuǎn)移到一個精致的小餐館。

{
  "name": "Future Studio Steak House",
  "owner": {
    "name": "Christian",
    "address": {
      "city": "Magdeburg",
      "country": "Germany",
      "houseNumber": "42A",
      "street": "Main Street"
    }
  },
  "cook": {
    "age": 18,
    "name": "Marcus",
    "salary": 1500
  },
  "waiter": {
    "age": 18,
    "name": "Norman",
    "salary": 1000
  }
}

這來自于我們的API接口,并且我們要利用Gson去自動創(chuàng)建匹配的Java對象。首先,你需要模型化基礎(chǔ)類,所有頂級字段都在里面:

public class Restaurant {  
    String name;

    Owner owner;
    Cook cook;
    Waiter waiter;
}

看一下我們是如何為name創(chuàng)建一個String字符串,以及另外三個擴(kuò)展的Java類?有些人自已實現(xiàn)了代碼,可能與下面的結(jié)果不同。事實上,創(chuàng)建一個Java對象并不需要太明確。例如,基于JSON,我們看到了有一樣結(jié)構(gòu)的cookwatier嵌套對象。你可以仍然創(chuàng)建一個不同的類,像上面做的一樣,或者為他們倆只創(chuàng)建一個普通的Staff類。

public class Restaurant {  
    String name;

    Owner owner;
    Staff cook;
    Staff waiter;
}

其實,兩個方法任意一個都可行。如果你還不確定用哪個,我們通常會創(chuàng)建一個額外的類避免未來可能發(fā)生的沖突。例如,如果cook模型改變了,但是waiter模型保持不變,你可能需要改變一堆代碼。這樣,我們暫時拋棄Staff的解決方案。當(dāng)然,我們?nèi)砸獮榈诙哟蔚膶ο髣?chuàng)建Java模型類:

public class Owner {  
    String name;

    UserAddress address;
}

public class Cook {  
    String name;
    int age;
    int salary;
}

public class Waiter {  
    String name;
    int age;
    int salary;
}

好的,因為這個UserAddress類到哪都能適用,我們作了一點弊,第一部分重復(fù)使用了UserAddress。 ;-)

總之,我們希望你理解從一個JSON字符串創(chuàng)建Java模型類的過程。你需要從高層到最深層次遍歷,直到你的嵌套JSON只剩下常規(guī)類型。

既然主要工作已經(jīng)完成了,我們可以把一切交給Gson。當(dāng)然,如果我們之前所做的工作都是正確的,它會優(yōu)雅地處理一切,并創(chuàng)建只有幾行的Java對象:

String restaurantJson = "{ 'name':'Future Studio Steak House', 'owner':{ 'name':'Christian', 'address':{ 'city':'Magdeburg', 'country':'Germany', 'houseNumber':'42', 'street':'Main Street'}},'cook':{ 'age':18, 'name': 'Marcus', 'salary': 1500 }, 'waiter':{ 'age':18, 'name': 'Norman', 'salary': 1000}}";

Gson gson = new Gson();

Restaurant restaurantObject = gson.fromJson(restaurantJson, Restaurant.class);  

restaurantObject對象自動地包含了JSON里的所有的信息 :

提示:從JSON創(chuàng)建Java模型類是一項單調(diào)乏味的工作。在你掌握了概念后,你可能想要使用工具自動化處理。我們相當(dāng)喜歡用jsonschema2pojo.org。

展望

在這篇博客中,我們已經(jīng)學(xué)會了如何用Gson處理嵌套對象。對于Gson序列化復(fù)雜的數(shù)據(jù)類型已經(jīng)不是問題。甚至反序列化也不是啥大問題,但是你必須首先做一些創(chuàng)建合適模型類的工作。

如果你要反饋或提問,可以在評論里讓我們知道,或者twitter@futurestud_io

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文鏈接:Gson — Mapping of Nested Objects作者:Norman Peitek 翻譯:...
    簽到錢就到閱讀 3,301評論 2 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評論 19 139
  • 原文鏈接:Gson — Mapping of Arrays and Lists of Objects原文出自:No...
    無名小子的雜貨鋪閱讀 13,966評論 2 17
  • 鄭州吃素齋其實應(yīng)去永泰寺,邊吃邊猜。“ 郝東家素食部落”我第一次來,看見“素食部落”幾個字其實我內(nèi)心是拒絕的,對于...
    咪咕江閱讀 444評論 2 0
  • 遠(yuǎn)距離的美是欣賞, 近距離的痛是迷惘。 當(dāng)距離漸變漸遠(yuǎn)時, 回憶便開始囂張。 入夜的路燈, 把痛點亮。
    湯TOYOUTA閱讀 263評論 0 0

友情鏈接更多精彩內(nèi)容