5

I serialize data in server:

Gson gson = new Gson();
Map<String, List<?>> resultMap = BackendUpdateManager.getInstance()
    .getUpdates(timeHolder, shopIdInt, buyerIdInt);
gson.toJson(resultMap);

and deserialize:

Gson gson = new Gson();
Map<String, List<?>> resultMap =  gson.fromJson(json,
    new TypeToken<Map<String, List<?>>>() {
    }.getType());

However, when I try use items from the Map:

List<ProductCategory> productCategoryList = (List<ProductCategory>)updateMap.get(key);

for(ProductCategory productCategory : productCategoryList) {

}

I get error:

Caused by: java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.model.entity.ProductCategory

How can I fix this error or otherwise create a Map with List<different classes>?

I've tried creating classes with getters and setters, that contains Lists of different classes instead of Map<String, List<?>> and use it for serialization and deserialization. But I'm looking for a better way.

durron597
  • 31,968
  • 17
  • 99
  • 158
ViT-Vetal-
  • 2,431
  • 3
  • 19
  • 35
  • If you know it's a `Map>`, why did you deserialize it as a `Map>`? – azurefrog Apr 27 '15 at 08:12
  • @azurefrog It is not only List. Different keys different types: `updateMap.get(key)` – ViT-Vetal- Apr 27 '15 at 08:33
  • As the error points: when you deserialize with ? GSON and also JACKSON use some kind of map to deserialize the string and you need to do the mapping by yourself. – igreenfield Apr 27 '15 at 09:38
  • @igreen when I try use objects from List> after deserialize. This error happens when is incorrect deserialization http://stackoverflow.com/questions/10356140/how-can-i-use-google-gson-to-deserialize-a-json-array-into-a-a-collection-of-a-g – ViT-Vetal- Apr 27 '15 at 09:55

1 Answers1

2

How is Gson supposed to know that a particular Json string is a ProductCategory? For instance, if the definition of ProductCategory is this:

package com.stackoverflow.vitvetal;  

public class ProductCategory {
    String name;
    String type;
}

And the Json is this:

{
    "name":"bananas",
    "type":"go-go"
}

Where is the link that tells Gson to create an instance of a com.stackoverflow.vitvetal.ProductCategory?

This link doesn't exist, because you didn't tell Gson about it.

So what gson does instead is, it creates a Map<String, String> that looks like

"name" -> "bananas"
"type" -> "go-go"

If you want to do something different, the easiest thing to do - but also the least powerful - is to fully specify the parameterized type when you create your TypeToken; no wildcard <?> allowed.

If you need to do something more powerful, like creating maps with more variety in objects, you need to create a custom deserializer, using a TypeAdapter<T>, that teaches Gson how to handle your particular sort of object.

Community
  • 1
  • 1
durron597
  • 31,968
  • 17
  • 99
  • 158