Reputation:
I have two HashMaps to be serialised to JSON using Google Gson library:
final Map<String, String> map1 = new HashMap<String, String>() {
{
put("abc", "def");
}
};
final Map<String, String> map2 = new HashMap<String, String>();
map2.put("abc", "def");
final Gson gson = new Gson();
final String s1 = gson.toJson(map1); // "null"
final String s2 = gson.toJson(map2); // {"abc":"def"}
Why is the second HashMap correctly serialized but not the first HashMap?
Upvotes: 5
Views: 512
Reputation: 11984
Gson uses reflection and doesn't care whether or not a class implements Serializable
. Gson does, however, need a no-arg constructor (see the design doc):
Gson needs to create a dummy class instance before it can deserialize Json data into its fields ... we create class instances by invoking the parameterless constructor ...
When you call toJson(Object obj)
Gson will use obj.getClass()
to figure out how to construct a "dummy instance" of obj
which in your case is an anonymous inner class. Inner classes require a reference to their containing class in order to be constructed. The reference to the outer class is not available at the time of serialization which is why your result is null
. You can get around this issue by providing Gson with a little more information about how to construct your object:
final Map<String, String> map1 = new HashMap<String, String>() {
{
put("abc", "def");
}
};
Gson gson = new Gson();
String json = gson.toJson(map1, new TypeToken<Map<String, String>>() {}.getType()); // {"abc":"def"}
Edit: Note that this only works because your anonymous class can be cast to Map<String, String>
. If you had a more complex inner class such as:
final Map<String, String> map1 = new HashMap<String, String>() {
private String additionalData = "Foo";
{
put("abc", "def");
}
};
additionalData
would not be in the output.
Upvotes: 6