Gson——嵌套對(duì)象的映射

原文鏈接:Gson — Mapping of Nested Objects

作者:Norman Peitek

翻譯:簽到錢就到

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

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

Gson系列概覽

  1. 用java-JSON實(shí)現(xiàn)序列化合反序列化
  2. 嵌套對(duì)象的映射
  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

嵌套對(duì)象的序列化

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

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

現(xiàn)在我們的user也有了一個(gè)家庭地址幕庐,這個(gè)家庭地址也有自己的模型類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;
}

換句話說(shuō)久锥,user現(xiàn)在是用一個(gè)UserNested模型表示,其中有一個(gè)額外的一對(duì)一的地址對(duì)象。地址是在UserAddress模型中表示的异剥。

在java中瑟由,這兩個(gè)模型能夠通過(guò)類清晰地區(qū)分,并且我們通過(guò)UserAddress userAddress字段保持引用冤寿。然而歹苦,在JSON里,沒(méi)有類或引用督怜。只有嵌套nest)用戶地址到用戶對(duì)象中殴瘦。基本地号杠,在JSON里我們只要用{}在字段名字后創(chuàng)建一個(gè)新的對(duì)象:

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

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

不同于其他屬性(age蚪腋,email,...),新的userAddress沒(méi)有直接的值究流。而是有一些包含在{}內(nèi)的子值辣吃。很重要的一點(diǎn),需要你理解字段名字后面有括號(hào)的就是表明這是一個(gè)嵌套對(duì)象芬探。

太多的理論神得。是時(shí)候見識(shí)一下Gson從UserNested對(duì)象中創(chuàng)建了什么。你可能認(rèn)識(shí)這個(gè)模式偷仿,Gson不需要任何配置哩簿。它會(huì)自動(dòng)根據(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)該會(huì)很好奇,字符串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又一次按照字母順序存儲(chǔ)了字段节榜,但結(jié)果正是我們期望的。Gson正確地創(chuàng)建了嵌套userAddressJSON對(duì)象别智。當(dāng)然宗苍,我們可以為用戶的薪水方法或工作地址增加更多的嵌套對(duì)象。甚至嵌套對(duì)象里也能有嵌套對(duì)象!

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

嵌套對(duì)象的反序列化

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

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

{
  "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
  }
}

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

public class Restaurant {  
    String name;

    Owner owner;
    Cook cook;
    Waiter waiter;
}

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

public class Restaurant {  
    String name;

    Owner owner;
    Staff cook;
    Staff waiter;
}

其實(shí)硅卢,兩個(gè)方法任意一個(gè)都可行射窒。如果你還不確定用哪個(gè),我們通常會(huì)創(chuàng)建一個(gè)額外的類避免未來(lái)可能發(fā)生的沖突将塑。例如脉顿,如果cook模型改變了,但是waiter模型保持不變点寥,你可能需要改變一堆代碼艾疟。這樣,我們暫時(shí)拋棄Staff的解決方案。當(dāng)然蔽莱,我們?nèi)砸獮榈诙哟蔚膶?duì)象創(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;
}

好的误褪,因?yàn)檫@個(gè)UserAddress類到哪都能適用,我們作了一點(diǎn)弊碾褂,第一部分重復(fù)使用了UserAddress兽间。 ;-)

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

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

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對(duì)象自動(dòng)地包含了JSON里的所有的信息 :

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

展望

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

如果你要反饋或提問(wèn)痹籍,可以在評(píng)論里讓我們知道,或者twitter@futurestud_io

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晦鞋,一起剝皮案震驚了整個(gè)濱河市蹲缠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悠垛,老刑警劉巖线定,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異确买,居然都是意外死亡斤讥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門拇惋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)周偎,“玉大人,你說(shuō)我怎么就攤上這事撑帖∪乜玻” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵胡嘿,是天一觀的道長(zhǎng)蛉艾。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么勿侯? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任拓瞪,我火速辦了婚禮,結(jié)果婚禮上助琐,老公的妹妹穿的比我還像新娘祭埂。我一直安慰自己,他們只是感情好兵钮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布蛆橡。 她就那樣靜靜地躺著,像睡著了一般掘譬。 火紅的嫁衣襯著肌膚如雪泰演。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天葱轩,我揣著相機(jī)與錄音睦焕,去河邊找鬼靴拱。 笑死缔御,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妇蛀。 我是一名探鬼主播评架,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼培遵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼籽腕!你這毒婦竟也來(lái)了皇耗?” 一聲冷哼從身側(cè)響起万伤,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤迅矛,失蹤者是張志新(化名)和其女友劉穎虹钮,沒(méi)想到半個(gè)月后芜抒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宅倒,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹭劈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缓淹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讯壶。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡立轧,死狀恐怖氛改,靈堂內(nèi)的尸體忽然破棺而出胜卤,到底是詐尸還是另有隱情瑰艘,我是刑警寧澤紫新,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布囤耳,位于F島的核電站充择,受9級(jí)特大地震影響椎麦,放射性物質(zhì)發(fā)生泄漏观挎。R本人自食惡果不足惜嘁捷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缓升。 院中可真熱鬧,春花似錦尺棋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)净当。三九已至内斯,卻和暖如春蕴潦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俘闯。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工真朗, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留此疹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓旗扑,卻偏偏與公主長(zhǎng)得像眠菇,于是被迫代替她去往敵國(guó)和親祟昭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谜叹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

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