0

I have the following code as example of what I am trying to achieve:

public static void main(String args[]) {

    Map<String, Object> map = new HashMap<String, Object>();
    map.put("1", new A());  
    map.put("2", new B());
    String json = new Gson().toJson(map);
    Type type = new TypeToken<Map<String, Object>>(){}.getType();
    map = new Gson().fromJson(json, type);
    A a = (A) map.get("1"); 
    B b = (B) map.get("2");

}

static class A {

    int inum = 1;
    double dnum = 1.0;
    String str = "1";

}

static class B {

    int inum = 2;
    double dnum = 2.0;
    String str = "2";

}

The following code result in this exception:

Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to ParseJson$A
    at ParseJson.main(ParseJson.java:19)

So the question is: How to get the correct instances inside of a generic HashMap being serialized and deserialized by Gson?

Nom1fan
  • 846
  • 2
  • 11
  • 27

1 Answers1

2

Object is deserialized into com.google.gson.internal.LinkedTreeMap, so tell Gson that you want the A class.

public static void main(String args[]) {
    Map<String, Object> map = new HashMap<>();
    map.put("1", new A());
    String json = new Gson().toJson(map);
    Type type = new TypeToken<Map<String, A>>() {
    }.getType();
    map = new Gson().fromJson(json, type);
    A a = (A) map.get("1");
    System.out.println(a.str);
}

static class A {
    private int num1 = 1;
    private double num2 = 2.0;
    private String str = "String";
}

Hope it helps.

UPDATE

A base class (X in this case) could be a solution:

public static void main(String args[]) {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("1", new A());
    map.put("2", new B());
    String json = new Gson().toJson(map);
    Type type = new TypeToken<Map<String, X>>(){}.getType();
    map = new Gson().fromJson(json, type);
    X a = (X) map.get("1");
    X b = (X) map.get("2");
    System.out.println(a.str);
    System.out.println(b.str);
}

static class X {
    int inum;
    double dnum;
    String str;

    X() {
    }
}

static class A extends X {
    A() {
        inum = 1;
        dnum = 1.0;
        str = "1";
    }
}

static class B extends X {
    B() {
        inum = 2;
        dnum = 2.0;
        str = "2";
    }
}
totoro
  • 2,469
  • 2
  • 19
  • 23
  • Your answer was correct, but I am actually trying to achieve something a bit more complex. I updated the question body to illustrate. I am defining the HashMap with Object for a reason. Because I need to include different types. Thanks! – Nom1fan Apr 26 '16 at 19:08
  • It seems I oversimplified my case again :) Although your answer is correct again in the case I have given. In my real case the classes don't have a real similarity between them (Can just be String, enum, or any other class..) But I'm starting to think there is no elegant solution for that. What I am doing right now is just using valueOf for variables there are interpreted as a paraceable type of the original. But for complex classes I have no solution so I just broke their fields apart and pass them separately... – Nom1fan Apr 26 '16 at 20:13