Vitali Melamud
Vitali Melamud

Reputation: 1397

JSON Serialization of Subclass to Superclass

I have two classes:

Superclass:

public class A
{
    public int a;

    public A(int a)
    {
        this.a = a;
    }
}

Subclass:

public class B extends A
{
    public B(int a)
    {
        super(a);
    }
}

I use Jackson to serialize/deserialize instances of A & B.

I would like class B to be serialized to A. I would expect this to be straight forward as B doesn't have any members. But I get an exception from Jackson and the only solution I've found is declaring B as a subtype of A - and I don't want to use this solution because this way B is serialized and deserialized to B.

My limitation is that I can't create another classes to contain A/B (container).

Upvotes: 1

Views: 2403

Answers (1)

Marc Q.
Marc Q.

Reputation: 551

If you have a container class, Jackson should deserialize to the type in the container class. I have renamed A to Animal and B to Bird.

public class Container {
  public Animal animal;

  public Container() {}

  public static class Animal {
    public Animal() {}
    public Animal(int age) {
      this.age = age;
    }
    public int age;
  }

  public static class Bird extends Animal {
    public Bird() {}
    public Bird(int age) {
      super(age);
    }
  }
}

When serializing a Container object with a Bird and then deserializing it, it will become an Animal.

@Test
public void fromBirdToAnimal() throws IOException {
  Container one = new Container();
  one.animal = new Container.Bird(123);
  String json = new ObjectMapper().writeValueAsString(one);

  Container two = new ObjectMapper()
    .readerFor(Container.class).readValue(json);
  assertEquals(123, two.animal.age);
  assertEquals(Container.Animal.class, two.animal.getClass());
}

If a container class is not possible but you know the class you need (the root class of your inheritance tree), telling ObjectMapper.readerFor could help you out.

@Test
public void fromBirdToAnimal() throws IOException {
  Container.Bird one = new Container.Bird(123);
  String json = new ObjectMapper().writeValueAsString(one);

  Container.Animal two = new ObjectMapper().readerFor(Container.Animal.class).readValue(json);
  assertEquals(123, two.age);
  assertEquals(Container.Animal.class, two.getClass());
}

Upvotes: 1

Related Questions