And on we go. After going through Jackson 2.7 feature set, we are ready to inspect contents of the very latest Jackson minor release from 2 months ago (July 2016).

As usual, the full 2.8 release notes tell the whole story; here we will look at the big ticket items.

Bit Bigger Minor Release

Compared to 2.7, this release contains a bigger ball of features but no significant rewrite of internals (2.7 contained a full rewrite of type resolution subsystem). Most changes and improvements are incremental, with “Config overrides” perhaps the most significant completely new feature (see below).

Compatibility

No major changes to JDK baseline (still need Java 7 to compile, but can use on Java 6 systems as Java 7 functionality is dynamically loaded).

One significant change to YAML module is that instead of shading SnakeYAML (as before), it is now just included as dependency. The change was done to help with OSGi usage where shading can be problematic; but does mean that if build system does not automatically fetch dependencies, SnakeYAML jar needs to be included along with YAML module.

One change in XML module is to add explicit dependency to Woodstox to use it as the default Stax implementation (overridable via Maven dependencies if need be, to use Aalto for example); earlier it was only a `test` dependency.
Intent here is to reduce issues that come with somewhat lackluster Stax implementation that JDK bundles, and that users may be unintentionally relying on simply as a default choice.

Finally, JAX-RS dependency was increased from 1.1 to 2.0: that is, JAX-RS providers module is compiled against JAX-RS 2.0 API, and expects 2.0 runtime.

Modules

2.8 introduces two new modules

  • Java Properties format module.
  • JAX-RS datatype module, to support a small set of JAX-RS (2.0) datatypes like `javax.ws.rs.core.Link` (note: this module is included as part of `jackson-jaxrs-providers` git repo)

Aside from usual bug fixes, biggest improvements were for

For details of changes for these, refer to relevant sections of 2.8 Release notes.

New functionality

As the ninth official format module (counting JSON itself as the first), Java Properties adds support for the textual format that is widely used in Java world for configuration (and with some configuration options even more widely with similar “properties-like” systems).

A simple example (from the earlier article on subject) is:

title=Home Page
site.host=localhost
site.port=8080

which could be bound to a POJO like:

public class Endpoint {
public String title;
public Site site;
}
public class Site {
public String host;
public int port;
}

In addition to basic reading/writing of Properties from/to Files and other usual sources, there are convenience methods (via `JavaPropsMapper`), and a simple schema (`JavaPropsSchema`) for customizing optional aspects like value separator to use (default: ‘=’).

For more details, read “Reading/writing Java properties files using Jackson”, which contains full feature overview.

So this is the major new feature mentioned earlier. The idea is to provide an alternative to class annotations, so that instead of, or in addition to, adding annotations, it should be possible to configure type-based defaults for things for which you would normally use annotations like:

  • `@JsonInclude`: excluding properties with specific values — like `null`, or Empty `List`s — from being written out
  • `@JsonFormat`: defining formatting aspects of serialization, and for some things deserialization as well — for example, date format to use
  • `@JsonIgnoreProperties`: defining a list of properties that should be ignored on reading/writing, similar to per-property `@JsonIgnore`
  • `@JsonIgnoreType`: ignoring ALL properties of specified type (usually some internal type attached as metadata)

One way to think of this is to consider it as an alternative to annotations.
So, for example, earlier you would have had to apply type ignoral on class itself (either directly, or through mix-in annotations):

@JsonIgnoreType
public class Internal { // not serializable

}
public class POJO {
private Internal state;
public Internal getState() { return state; }
// ...
}

(and the reason for using `@JsonIgnoreType` is to avoid having to explicitly add `@JsonIgnore` on every reference)

With 2.8, you can instead achieve the same using:

ObjectMapper mapper = …;
mapper.configOverride(Internal.class).setIsIgnoredType(true);

Or, for this specific case you could also have used:

mapper.setIgnorals(JsonIgnoreProperties.Value.forIgnoredProperties(
"state"));

as an alternative to:

@JsonIgnoreProperties({ “state” })
public class POJO {
...
}

Similarly, all aspects of `@JsonFormat` and `@JsonInclude` may be configured on per-type basis. Note that these settings will:

  • Have precedence over global defaults (for things that have those); that is, override any global defaults
  • Be potentially overridden by per-property annotations: that is, if property itself has `@JsonFormat`, settings from that will override any per-type defaults. Note that the design is such that you can choose to only specify certain parts — `@JsonFormat`, for example, has multiple aspects to set and you can omit things you do not want to change. This allows for multi-level defaulting; some things use global defaults, others are configured on per-type basis, and yet others may be specified by property-annotations.

The most important thing to note here is that the initial list of configuration features support is just a starting point: 2.9 and beyond will extend support for things where it makes sense.

Before 2.8, jackson-jr relied on having `public` getters and setters (as per Bean specification): 2.8 adds support for `public`fields as well. This can be particularly helpful on platforms like Android where there are limits on number of methods code components have, and/or bytecode size is minimized.

Note, too, that Jackson-jr was significantly improved with 2.7, so if you only previewed it with earlier versions, it may make sense to check its feature set again.

On some platforms, interfaces `java.io.DataInput` and `java.io.DataOutput` are the prime i/o abstractions: this is the case for many Hadoop-based systems. Before 2.8 it was necessary to use intermediate abstractions for buffering data to expose via `DataInput`/`DataOutput`.

With 2.8, output to `DataOutput` is supported with ALL dataformats; input from `DataInput` is supported for JSON. Support for some of other data formats may be added (there are preliminary plans for CBOR and Smile), based on user feedback, and feasibility of support (not all formats can be supported due to issues in end-of-input detection; `DataInput` does not allow look-ahead).

One of the areas that are still lacking with Jackson is the error handling: while errors are detected fairly well, information given to developer via exceptions is not very granular. Further, although there are configuration settings to allow ignoring/recovery of some problem cases, there isn’t much in a way of more advanced handling and optional failures.

One of few facilities for configurable error handling and recovery that existed before 2.8 was `DeserializationProblemHandler`: an implementation may be registered with `ObjectMapper`. But it only contained one method, `handleUnknownProperty()`, to allow recovering from encountering a (JSON) property with name that does not map to a known property of the target type.

With 2.8, 7 new methods were added to allow improved error reporting and/or recovery from other deserialization problems, such as unexpected format for key and value types; invalid or missing Type Id (for polymorphic handling) and missing/mismatching constructor (creator in general). Check Javadoc for more details.

Another minor addition is the new annotation — `@JsonEnumDefaultValue` — which is to be used with `DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE`, and if so allows defaulting of otherwise unknown values. This can be useful for interoperability and forward-compatibility.

For null-hates amongst us, this feature allows throwing of a `JsonMappingException` if an attempt is made to bind a `null` via creator parameter — both via explicit `null` from input, and from just missing a value.

Note: only applies to properties passed via properties-based Creator method (`@JsonCreator`annotated, `Mode.PROPERTIES`); not for other `null` assignments.

Written by

Open Source developer, most known for Jackson data processor (nee “JSON library”), author of many, many other OSS libraries for Java, from ClassMate to Woodstox

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store