Gson — Mapping of Maps

After publishing multiple blog posts on how to work with a variety of data types, we'll explore working with Java Maps in this one. You'll learn how to (de)serialize Java Maps using the Gson library.

Of course, this is not the only post in our Gson series. If you're interested in other topics, check out our series outline:

Gson Series Overview

Serialization of Java Maps

Java maps are a very flexible data type and can be used for an assortment of scenarios. It allows us developers to materialize a lot of real-world situations in the Java programming language. Since Java maps are used in such a variety we probably won't cover your exact use case, but the approach applies for all of them.

Let's start with the scenario that your app has a list of employee names. You were asked to implement a view to show all employees which start with a specific first letter. For example, the user can select the letter A and your application would return the three matching employees Andreas, Aden and Arnold. The first iteration was just a list with all names, but the performance wasn't good enough. Thus, the implementation was switched to a HashMap where the key is the first letter (i.e. A) and the value is a list of names.

If we create our HashMap our Java code would look like this:

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"));  

The serialization of maps is the same as with any other type. You can just throw it at Gson and it'll do the correct thing:

Gson gson = new Gson();  
String employeeJson = gson.toJson(employees);  

This would result in this JSON:

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

The keys (A, C and M) each have a list of names, which is exactly what we wanted to describe.

Deserialization of Java Maps

If you look at the result JSON of the previous section, or the JSON below, you'll ask yourself: how can you spot the difference between a set and multiple objects? The simple answer is: you can't. This is one of the few instances where the JSON data representation is ambiguous. Let's look at the following example:

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

This is the JSON, where the reader could assume that there are three objects with the name 1$, 2$ and 3€. Each of these objects has some values. But on the other hand it can also be a simple Map where the 1$, 2$ and 3€ are keys.

There is no fool-proof way of evaluate what data type a JSON is. Some pointers to assist you are:

  • First and most important of all: context knowledge! If you've documentation or know what the objects are describing you should be able to interpret if there are separate objects or a map of data.
  • Is the data type of the value consistent? Then it hints toward a map.
  • Are the object names/keys dynamic and of a wide range? This also hints toward a map.

We've already shown you in a previous blog post how to map regular objects, so in this blog post we'll assume the JSON is a map of data. How can we map the JSON shown above to Java objects?

We can use the same TypeToken approach we've shown you in the List of Objects blog post. You create an appropriate Type by creating a new TypeToken with our expected data 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);

The amountCurrency variable actually holds the full set with the correct keys and values:

Nested Maps

Map data structures don't have to be the root element of the model/JSON. It can be just a property of an object. You'd (de)serialize it the same way like you've to with lists. We already published a guide for nested behavior here.

Outlook

In this blog post you've seen how you can serialize and deserialize Java maps from and to JSON. You've learned the potential obstacles and how to overcome them. In the next blog post we'll look at the very similar Java data type Sets. Stay tuned!

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.