翻譯:簽到錢就到
在發(fā)布了多篇關(guān)于如何處理不同數(shù)據(jù)類型的文章之后祥国,我們會在這篇文章中處理Java的Map類型。你會學(xué)習(xí)如何使用Gson庫去序列化(反序列化)Java的Map斯嚎。
當(dāng)然,這不是我們Gson系列里唯一的一篇文章凌摄,如果你對其他的主題感興趣另锋,可以看一下我們的大綱:
Gson系列概覽
- 用java-JSON實現(xiàn)序列化合反序列化
- 嵌套對象的映射
- 數(shù)組和列表對象的映射
- Map的映射
- Mapping of Sets
- Mapping of Null Values
- Gson Model Annotations — How to Ignore Fields with @Expose
- Gson Model Annotations — How to Change the Naming of Fields with @SerializedName
- Gson Builder — Basics & Naming Policies
- Gson Builder — Force Serialization of null Values
- Gson Builder — Exclusion Strategies
- Gson Builder — Relax Gson with Lenient
- Gson Builder — Special Values of Floats & Doubles
- Gson Builder — Model Versioning
- Gson Builder — Formatting of Dates & Custom Date/Time Mapping
- Gson Builder — Pretty Printing
- Gson Builder — HTML Escaping
Java中Map的序列化
Java的Map是一個非常靈活的數(shù)據(jù)類型俊柔,可以被用在各種各樣的場景中。它允許我們開發(fā)者用Java語言去物化許多真實世界的情況枫夺。由于Java的Map使用非常廣泛磅网,我們可能不會覆蓋到你正在用的案例,但將會覆蓋到所有的方法筷屡。
讓我們用一個場景來開始涧偷,你的應(yīng)用有員工姓名的列表,你被要求去實現(xiàn)一個以某個特定字母開頭的所有員工展示界面毙死。例如燎潮,用戶可以選擇字母A
,此時扼倘,你的應(yīng)用會返回三個匹配的員工名字:Andreas
确封、Aden
和Arnold
。第一次迭代只是列出了所有名字的列表再菊,但是性能往往是不夠的爪喘。因此,轉(zhuǎn)去使用HashMap
實現(xiàn)纠拔,第一個字母作為鍵(Key)(如:A
)秉剑,值將是一個名字的列表。
如果我們創(chuàng)建我們的HashMap
,我們的Java代碼將會是這樣:
HashMap<String, List<String>> employees = new HashMap<>();
employees.put("A", Arrays.asList("Andreas", "Arnold", "Aden"));
employees.put("C", Arrays.asList("Christian", "Carter"));
employees.put("M", Arrays.asList("Marcus", "Mary"));
Map的序列化與其他類型是一樣的稠诲,你可以將其直接傳給Gson侦鹏,Gson會正確地處理:
Gson gson = new Gson();
String employeeJson = gson.toJson(employees);
返回的JSON數(shù)據(jù):
{
"M": [
"Marcus",
"Mary"
],
"C": [
"Christian",
"Carter"
],
"A": [
"Andreas",
"Arnold",
"Aden"
]
}
每個鍵(A
,C
和M
)都有自己的名字列表诡曙,這正是我們想要的。
Java中Map的反序列化
如果你看了前面一節(jié)的JSON數(shù)據(jù)略水,或者下面的JSON數(shù)據(jù)价卤。你會問你自己:如何才能區(qū)分一個集合和多個對象呢?答案很簡單:你不能渊涝。這是為數(shù)不多的幾個特性之一,JSON數(shù)據(jù)表示是模棱兩可的慎璧。看看下面的列子:
{
"1$": {
"amount": 1,
"currency": "Dollar"
},
"2$": {
"amount": 2,
"currency": "Dollar"
},
"3€": {
"amount": 3,
"currency": "Euro"
}
}
在JSON中跨释,讀者可以假設(shè)有名字分別是1$
炸卑、2$
和3€
的3個對象,每個對象都有自己的值煤傍。但另一方面也能被看作是一個簡單的Map盖文,1$
、2$
和3€
是鍵(Key)蚯姆。
沒有可靠的方法評估一個JSON數(shù)據(jù)類型是什么五续。這里提供一些關(guān)鍵點來幫助你:
- 第一且最重要的:上下文知識!如果你有文檔或已經(jīng)知道所描述的對象應(yīng)該是怎樣的斑粱,你應(yīng)該能夠區(qū)分單獨的對象和Map數(shù)據(jù)割卖。
- 值的數(shù)據(jù)類型是一致的嗎?一致的就可能是Map
- 對象名稱/鍵是動態(tài)的和廣泛的嗎?這也是Map類型的提示。
我們可以使用在列表對象文章中展示的TypeToken
方法昏翰。你用我們期望的數(shù)據(jù)類型通過創(chuàng)建一個新的TypeToken
得到一個Type方法:
public class AmountWithCurrency {
String currency;
int amount;
}
String dollarJson = "{ '1$': { 'amount': 1, 'currency': 'Dollar'}, '2$': { 'amount': 2, 'currency': 'Dollar'}, '3€': { 'amount': 3, 'currency': 'Euro'} }";
Gson gson = new Gson();
Type amountCurrencyType =
new TypeToken<HashMap<String, AmountWithCurrency>>(){}.getType();
HashMap<String, AmountWithCurrency> amountCurrency =
gson.fromJson(dollarJson, amountCurrencyType);
amountCurrency
變量實際上持有了整個正確的鍵郭毕、值集合:

嵌套的Map
Map數(shù)據(jù)結(jié)構(gòu)不會成為模型/JSON的根元素它碎。它只能是一個對象的屬性。你得用像處理列表一樣的方式序列化和反序列化它显押。我們也在這里發(fā)布了為嵌套行為的指導(dǎo)方式扳肛。
展望
本文中,你學(xué)習(xí)了如何在JSON數(shù)據(jù)和Java的Map之間序列化和反序列化乘碑。你也學(xué)習(xí)了可能遇見的問題挖息,以及如何克服的方法。下篇博客兽肤,我們會研究與Map非常相似的數(shù)據(jù)類型Set
套腹。請繼續(xù)關(guān)注!
如果你需要反饋或有疑問,在評論中讓我們知道或twitter @futurestud_io。