Skip to end of metadata
Go to start of metadata

NOTE: this page is being obsoleted by [the new Jackson Annotations page ].


Data Binding Deep Dive

Beyond simple examples shown on Tutorial , there is plenty more to know regarding Jackson Data Binding.

This page tries to give a deeper drill-down on how data-binding annotations work with Jackson.

What types are supported?

Jackson tries to automatically support such types that are commonly needed for data transfer, such as:

  • Primitive types (boolean, byte, short, int, long, float, double) and their Wrappers
  • Simple core types (Strings, Dates/Calendars, BigDecimal)
  • Standard collection (java.util.Collection) types (Sets, Lists, Maps), including full Generic type introspection
  • POJOs that implement Bean interface (setters, getters)
  • Arrays of all supported types

Additionally, it is possible to use Annotations to help with Bean introspection, as well as use marker interfaces (JsonSerializable) for custom serialization.

It is also possible to configure components ObjectMapper uses to recognize custom mappings between types (Classes, or generic types defined using TypeReference class) and custom serializers.

How is Bean/POJO property introspection implemented?

There are multiple complementary methods that Jackson uses to figure out what logical properties a Class has.

At basic level there are multiple design choices for data binding. For example:

  • Whether to base property discovery on Json content, Java object definitions, or external mapping (Schema)
  • If Java objects are used for discovery, whether to use member fields or methods.

Jackson chooses following strategy:

  • No information is injected into (or read from) Json: only Java Object definitions are used to determine properties instances have. No Schema are used either. (note: it is possible that in future some additional information may be used – especially so-called "mix-in annotations").
  • member methods (and related annotations for methods, classes) are used for property discovery. Certain kinds of static methods can be designated as factory methods.
  • Additionally, version 1.1 will also support use of member fields (public fields or ones explicitly annotated).
    • In case of conflicts (both a field and method map to same logical property name), "method wins" i.e. has higher precedence. This is not an error condition: accessor method is used instead of direct field access.
    • NOTE: it is often better to use method-based access for design reasons (methods can be declared in interfaces), as well as possibly performance reasons (perhaps non-intuitively Reflection access through methods is faster than direct field access).

Discovery uses the standard Bean naming to determine methods to use:

  • "setters" are needed for de-serialization:
    • property name is derived from method name, but can be overridden by annotation @JsonSetter
    • setter methods NEED NOT be public; data binder can access protected, default and private access methods.
    • otherwise eligible setter methods can be disabled with @JsonIgnore annotation
    • auto-discovery of setters can be disabled using @JsonAutoDetect annotation with suitable parameters.
  • "getters" are needed for serialization:
    • property name is derived from method name, but can be overridden by @JsonProperty (Jackson 1.1+) or @JsonGetter (legacy 1.0 annotation)
    • getter methods MUST be public to be discovered; OR need to be annotated as getters otherwise. In latter case access modifier does not matter: data binder can access any and all methods as long as security manager allows that)
      • Jackson 1.0: annotation @JsonGetter is used
      • Jackson 1.1: annotation @JsonProperty OR @JsonSerialize is to be used (former can specify logical property name)
    • otherwise eligible getter methods can be disabled with @JsonIgnore annotation
    • auto-discovery of getters can be disabled using @JsonAutoDetect annotation with suitable parameters (or using SerializationConfig/DeserializationConfig#Feature.AUTO_DETECT_GETTERS).
  • Constructors are needed/used so that:
    • Default constructor is currently (as of 0.9.7) needed for de-serializing Json Objects (note: there are plans to allow use of other constructors in future) and Json Arrays
    • Single-argument constructors can be used for de-serializing Json String and Number values: ctor(String s) and ctor(int/long value respectively
  • Factory methods can also be used for de-serializing Json String and Number values:
    • static valueOf(String s)
    • static valueOf(int i)
    • static valueOf(long l)
    • There are plans to allow other constructors/factory methods used with @JsonCreator annotation (specifically, ones that take Json objects or perhaps Json arrays too)

With Jackson version 1.1, public fields can also be auto-detected (unless auto-detection is disabled using @JsonAutoDetect annotation; or using matching SerializationConfig/DeserializationConfig feature for disabling):

  • public non-static member fields can be auto-detected as properties

More on Annotations

As of version 1.0.0, following Annotations have been implemented:

General annotations

  • @JsonAutoDetect (class): which kinds of methods (setters, getters, creators) can be auto-detected, in addition to explicit marking using annotations
  • @JsonIgnore (method): annotation used to completely disregard annotated method, regardless of auto-detection or other annotations
  • (Jackson 1.1+) @JsonProperty (method, field) can be used to denote:
    • Property to serialize (when applied to a "getter" method)
    • Property to deserialize (when applied to a "setter" method)
    • Field-backed property to serialize and deserialize (when applied to a non-static member field)

Serialization annotations

  • @JsonValue (method): used to mark a method thats return value is to be used as serialization for the object; often used to mark String-producing methods (like "toString()") to produce JSON primitive value serialization
  • (Jackson 1.1+) @JsonSerialize (method, field) can be used to denote:
    • Explicit serializer to use, with using(JsonSerializer) property
    • Explicit type to use (instead of actual runtime type), with as(JsonSerializer) property (must be compatible with runtime type, i.e. supertype)
    • Which bean properties to include, based on value, with include() property: by default all properties are included, but can omit null-valued properties or properties with "default" value (value assigned by default bean constructor)

Jackson 1.0 also defined following legacy annotations

  • (Jackson 1.0) @JsonGetter* (method): used to mark getter methods, as well as configure "logical" (external) name of the associate property (if it needs to differ from Bean naming convention)
  • @JsonUseSerializer (method, class): used to specify serializer to use, instead of locating it based on runtime type
  • @JsonWriteNullProperties (class): used to suppress writing out of properties that have null value

Deserialization annotations

  • @JsonAnySetter (method): used to mark 2-argument (String == key, Object == value) method to call when an unknown property is encountered (instead of throwing an excpetion)
  • @JsonCreator (method): used to mark static methods to use for instantiating instances of type that contains method (must have single-argument signature with String/int/double argument). Needed for non-public methods, or ones named something other than "valueOf".
  • (Jackson 1.1+) @JsonDeserialize (method, field) can be used to denote:
    • Explicit deserializer to use, with using(JsonDeserializer) property
    • Explicit types to use with as(JsonSerializer) property (must be compatible with declared type, i.e. subtype)
      • Similarly keyAs() and contentAs() for specifying key type for Maps, content type for Collections, arrays.

Jackson 1.0 also defined following legacy annotations:

  • @JsonClass (method, class): used to specify concrete type to deserialize to, instead of declared type (must be same type or subtype)
  • @JsonKeyClass (method, class): similar to @JsonClass, but used with Map key values
  • @JsonSetter (method): similar to @JsonClass, but used with Map/Collection/array content values
  • @JsonUseDeserializer (method, class): used to specify deserializer to use, instead of locating it based on declared type
Labels
  • None