Skip to main content

Bean Subtypes

In addition to the bean type name support, Juneau provides simplified support for bean subtypes via the @Marshalled(dictionary=…) attribute declared on a parent bean class.

Bean subtypes are similar in concept to bean type names, with two convenience differences:

  • You declare the list of possible subclasses through an annotation on the parent bean class, rather than registering them individually.
  • You do not need to register the subtype classes on the bean dictionary of the parser — the parser discovers them from the parent class's dictionary.

Example​

In the following example, the abstract superclass declares its two concrete subclasses, and each subclass declares its _type name:

// Abstract superclass declares its subtypes.
@Marshalled(
dictionary={A1.class, A2.class}
)
public abstract class A {
public String f0 = "f0";
}

// Subclass 1
@Marshalled(typeName="A1")
public class A1 extends A {
public String f1;
}

// Subclass 2
@Marshalled(typeName="A2")
public class A2 extends A {
public String f2;
}

When serialized, the concrete subtype is emitted as a virtual _type property:

A1 object = new A1();
object.f1 = "f1";
String json = Json5.of(object);
assertEquals("{_type:'A1',f1:'f1',f0:'f0'}", json);

When parsed back into the abstract type, the _type property is used to instantiate the correct concrete subclass:

A object = Json.to(json, A.class);
assertTrue(object instanceof A1);

The _type property name​

The _type property name is the default type-discriminator key. It can be changed globally via MarshallingContext.Builder.typePropertyName(String), or per-class via @Marshalled(typePropertyName=…).

See also​