Gson 对 Map 结构进行映射

我们将在本篇文章中探讨如何使用 Java Map。 我们将学习如何使用 Gson 库(反)序列化 Java Map。


Java Map 的序列化

Java Map是一种非常灵活的数据类型,可用于各种场景。 它使我们的开发人员能够在 Java 编程语言中实现许多现实世界的情况。 由于 Java Map的使用范围如此之广,因此我们可能不会涵盖确切的用例,但该方法适用于所有这些用例。

让我们从应用具有员工姓名列表的场景开始。 我们被要求实施一个视图以显示以特定首字母开头的所有员工。 例如,用户可以选择字母 A,我们的应用程序将返回三个匹配的员工 AndreasAden 和 Arnold。 第一次迭代只是一个包含所有名称的列表,但性能还不够好。 因此,实现被切换到 HashMap,其中键是第一个字母(即 A),值是名称列表。

如果我们创建我们的 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 = new Gson();  
String employeeJson = gson.toJson(employees);  

这将会生成如下的JSON

{
  "M": [
    "Marcus",
    "Mary"
  ],
  "C": [
    "Christian",
    "Carter"
  ],
  "A": [
    "Andreas",
    "Arnold",
    "Aden"
  ]
}

每个键(AC 和 M)都有一个名称列表,这正是我们想要描述的。


Java Map 的反序列化

如果我们查看上一节的结果 JSON 或下面的 JSON,则会问自己:如何发现集合和多个对象之间的区别? 简单的答案是:你不能。 这是 JSON 数据表示不明确的少数情况之一。 让我们看下面的例子:

{
  "1$": {
    "amount": 1,
    "currency": "Dollar"
  },
  "2$": {
    "amount": 2,
    "currency": "Dollar"
  },
  "3€": {
    "amount": 3,
    "currency": "Euro"
  }
}

这是 JSON,大家可以假设存在三个名称为 1$ 、2$ 和 3€ 的对象。 这些对象中的每一个都有一些值。 但另一方面,它也可以是一个简单的 Map,其中 1$ 、2$ 和 3€ 是键。

没有万无一失的方法来评估 JSON 是什么数据类型。 一些可以帮助大家的建议是:

  • 首先也是最重要的:上下文知识! 如果有文档或知道对象所描述的内容,我们应该能够解释是否存在单独的对象或数据映射。
  • 值的数据类型是否一致? 然后它向 Map 提示。
  • 对象名称/键是否动态且范围广泛?
  • 我们已经在之前的文章中向大家展示了如何映射常规对象,因此在本篇文章中,我们将假设 JSON 是数据映射。 我们如何将上面显示的 JSON 映射到 Java 对象?

我们可以使用我们在 List of Objects 文章中向大家展示的相同 TypeToken 方法。 我们可以通过使用我们预期的数据类型创建一个新的 TypeToken 来创建一个适当的类型:

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 变量实际上保存了具有正确键和值的完整集合:

Gson 对 Map 结构进行映射

Map 数据结构不必是 模型/JSON 的根元素。 它可以只是一个对象的属性。 我们可以像使用列表一样(反)序列化它。 我们已经在这里发布了嵌套对象映射指南。

在这篇文章中,我们已经了解了如何从 JSON 序列化和反序列化 Java Map。 我们已经了解了潜在的障碍以及如何克服它们。 在下一篇文章中,我们将介绍非常相似的 Java 数据类型 Sets 的映射。