Feature: Polymorphic Type Handling, PTH, (formerly known as "Polymorphic Deserialization (and serialization))

0. Implementation Status

As of February 2010, this feature *is implemented*, and will be part of official Jackson 1.5 release!

(for more details, see Jira entry http://jira.codehaus.org/browse/JACKSON-91)

1. Definition

Polymorphism is an Object-Oriented Design concept that Java implements by class inheritance. Here it just means ability to construct instances of sub-classes of a given declared class, based on which sub-class was actually serialized. That is, even though during serialization the declared type is a super-type, it should be possible for the deserializer to properly resolve actual expected type of the value to assign.

Implementing support for polymorphic types is one of highest priority items for Jackson development. At the same time, implementation that covers require use cases (including cases where not all communicating systems run on Java platform) is not trivially simple to implement, so care has to be taken to create a simple, powerful and extensible design. To come up with such a design, let's first consider type design choices and alternatives that are available.

2. Design Choices

Instance Type Information (Type Metadata)

(aka "Type Id")

To be able to deserialize JSON object into types that instances were serialized from (and not just statically declared type, which is generally a supertype), some amount of per-instance type information is needed. There are multiple possible ways to do this. For example:

To give an idea of possible concrete examples of such instance type information, here are some examples (but please note that other choices discussed below would change actual mechanism of including type information):

  { // Using fully-qualified path
    "@class" : "com.fasterxml.beans.EmployeeImpl", ...
  }

  { // Using indirect type name
    "@type" : "Employee", ...
  }

  { // Fancy custom type information (can bind JSON object to a type object)
    "customType" : { "xmlType" : "http://foo.bar/schema.xsd", "preferredClass" : "com.foo.EmployeeClass" },
    ...
  }

Different mechanisms have different trade-offs; for example:

Methods for embedding Instance Type Information

(aka "Include As")

After deciding what type information (usually a Type Id of some kind) to add along with instance data, it is necessary to define how this information is to be included in actual JSON data. Some obvious methods of inclusion are:

Given examples from previous section, here are possible ways to embed class name information:

  // Type name as a property, same as above
  {
    "@type" : "Employee",
     ...
  }

  // Wrapping class name as pseudo-property (similar to JAXB)
  {
    "com.fasterxml.beans.EmployeeImpl" : {
       ... // actual instance data without any metadata properties
    }
  }

  // Wrapping class name as first element of wrapper array:
  [
    "com.fasterxml.beans.EmployeeImpl",
    {
       ... // actual instance data without any metadata properties
    }
  ]

Customizing type handling

Here are some aspects that should be customizable:

3. Implementation Plan

Current thinking is to support multiple Type Metadata methods as well as multiple inclusion methods. And since these are somewhat orthogonal, allow different combinations of the two. And finally make aspects configurable with sensible defaults, to try to fulfill sometimes conflicting goals of simplicity (as close to "zero configuration" as possible) and configurability (ability to customize behavior to exact needs and preferences).

As with other configurability for Jackson, emphasis will initially be on allowing configuration using Java Annotations. Benefits include some level of type-safety, as well as flexibility when using Annotation Mix-ins.

3.1 Baseline: global defaults

In addition to per-type definitions by annotations, it is necessary to allow setting of global baseline. There are two reasons why this is necessary:

  1. Convenience: although it may be technically possible to annotate all possible types (or might not...), it may be unfeasible for practical purposes. As such it is good to be able to define a default type handling baseline, different from default of "no type information".

(TO BE COMPLETED)

3.2 Per-type annotations

All annotations that do NOT depend on mapper types, will live in the main org.codehaus.jackson.annotate package. Other annotations (with dependencies) will live in org.codehaus.jackson.map.annotate package.

The main annotation used for indicating type is @JsonTypeInfo. It has following properties:

(TO BE COMPLETED)

3.3 Global type defaulting

(TO BE COMPLETED)


CategoryJackson

JacksonPolymorphicDeserialization (last edited 2010-02-14 03:20:19 by TatuSaloranta)

Copyright ©2009 FasterXML, LLC