user3146617
user3146617

Reputation: 101

Gson serializing a list of polymorphic objects

Overview, I have an abstract class from which three concrete classes inherit.

public abstract class A {}

public class B extends A {}

public class C extends A {}

public class D extends A {
   private List<A> children;
 }

Main point is that concrete class D has a list that could contain objects of concrete class B, C or D.

My challenge is how to serialize D given that its children could be of three different types; itself or the two other concrete classes. I have a working custom serializer that works if all the children are of the same type. Not looking for a full blown solution, a high level approach or strategy will be fine. Thanks.

Upvotes: 2

Views: 1063

Answers (2)

rpax
rpax

Reputation: 4496

Take a look to https://stackoverflow.com/a/22081826/3315914. There's a working example of it. All you need is Gson's RuntimeTypeAdapterFactory. A simple example could be:

RuntimeTypeAdapter<Shape> shapeAdapter = RuntimeTypeAdapterFactory.of(Shape.class)
        .registerSubtype(Rectangle.class)
        .registerSubtype(Circle.class)
        .registerSubtype(Diamond.class);

And then,

Gson gson = new GsonBuilder()
       .registerTypeAdapter(Shape.class, shapeAdapter)
       .create();

Also, here you can also find a similar answer.

I hope it helps.

Upvotes: 1

Brian Roach
Brian Roach

Reputation: 76898

I highly suspect you are using some ancient version of Gson or you're not explaining exactly what the problem is. Using v2.2.4 of Gson:

public class App
{
    public static void main(String[] args) 
    {          
        D d = new D();
        D d2 = new D();
        d.list.add(d2);
        System.out.println(new Gson().toJson(d));
    }
}

abstract class A
{
    private int a = 5;
}

class B extends A
{
    private int b = 6;
}

class C extends A
{
    private int c = 7;
}

class D extends A
{
    List<A> list = new ArrayList<A>();

    public D()
    {
        list.add(new B());
        list.add(new C());
    }
}

Output:

{"list":[{"b":6,"a":5},{"c":7,"a":5},{"list":[{"b":6,"a":5},{"c":7,"a":5}],"a":5}],"a":5}

As you can see, the inherited private field a from the abstract A is serialized correctly when B,C, and D are serialized.

Upvotes: 0

Related Questions