Jackson 2.14 sneak peek

It has been a while since Jackson 2.13 was released — about 9 months.
Since then there has been steady progress, with about 50 fixes, improvements and new features (see in-progress 2.14 release notes for details).
The plan is to get the first Release Candidate (2.14.0-rc1) out during August 2022. Let’s have a look at some of interesting improvements, features that will be included.

Another “minor minor” release

Most notable improvements can be found in following areas:

  1. Improvements to JSON parser (performance, support for more “non-standard” content reading, alternate non-blocking input source)
  2. Datatype-specific configurability for ObjectMapper (and ObjectReader / ObjectWriter)
  3. More ways to use JsonNode (Tree Model)

Compatibility: Java 8 now baseline for jackson-core, jackson-jr

This is not expected to have much impact for users but simplifies maintenance: users (if any) that require Java 6 or Java 7 compatibility will still be able to use 2.13.x patches.

Feature: Improved @JsonAnySetter handling

  1. 2-argument setter method (which gets called once per otherwise unmapped property), OR
  2. Map<String, T> valued non-null Field (in which case all otherwise unmapped properties are bound to an existing Map

But there had been long-running desire to extend this functionality to allow use of:

  • Non-initialized (null) Map wherein Map is dynamically created if (and only if) needed (databind#3559)
  • ObjectNode (JsonNode that represents JSON Object value) value Field (databind#3394)

So now you can use constructs like:

public class MapAnyBean {
// no need to initialize if one of "well-known" Map types:
@JsonAnySetter
public Map<String, Object> values;
}
public class JsonNodeBean {
// May initialize but no need to:
@JsonAnySetter
public ObjectNode valuesAsNodes;
}

neither of which would have worked with Jackson 2.13 or earlier.

Feature: ByteBuffer-backed non-blocking JSON parser

A long-standing — and Highly Voted! — wish (core#478) is now fulfilled: Jackson 2.14 will provide an alternate ByteBuffer backed implementation — it works the same way except for different NonBlockingInputFeeder (ByteBufferFeeder instead of ByteArrayFeeder). Refactoring work also means that it should now be much easier to add support for other non-blocking input sources.

Feature: Support for more Non-Standard “JSON” constructs

  • Optional/extra separators (trailing comma, missing values)
  • Flexible number representations
  • Optional comments

Existing options are mostly configurable using JsonReadFeature (see jackson-core wiki for links to specific Feature options). Jackson 2.14 will add 2 more settings that can be useful for things like (badly named) “JSON5” content:

  • JsonReadFeature.ALLOW_TRAILING_DECIMAL_POINT_FOR_NUMBERS (jackson-core#773) to allow floating-point numbers like 124. and -8.
  • JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS (jackson-core#774) to allow numbers with leading plus sign, like +25 and +0.17

Note: as per long-standing policy, all deviations from the strict JSON specification require to be explicitly enabled — they are not allowed by default.

Feature: FASTER floating-point number reading and writing

Features in question are:

  1. StreamReadFeature.USE_FAST_DOUBLE_PARSER (jackson-core#577)
  2. StreamWriteFeature.USE_FAST_DOUBLE_WRITER (jackson-core#749)

and are usually enabled by configuring JsonFactory like so:

JsonFactory f = JsonFactory.builder()
.enable(StreamReadFeature.USE_FAST_DOUBLE_PARSER)
.enable(StreamWriteFeature.USE_FAST_DOUBLE_WRITER)
.build();

One thing to note is that there is a possibility that the conversion between textual value and the internal Java floating-point value (for float, double; BigDecimal is not affected) may differ from that of conversion implemented by JDK: this is why the new read/write implementation is not enabled by default and has to be explicitly enabled by users.

Note, too, that in near future support will be added for other textual format backends too (CSV, Properties, TOML, XML, YAML). It is possible that this will be even included in 2.14 release.

We also hope to get some performance measurement numbers on difference these settings make — stay tuned!

Feature: datatype-specific configurability (JsonNodeFeature, EnumFeature?)

  • Generic databinding Features (DeserializationFeature, SerializationFeature, MapperFeature), affecting all content
  • Generic and Format-specific low-level stream read/write features (like JsonReadFeature, CsvWriteFeature etc)
  • Fully format-specific extensions through either format-specific schemas (CsvSchema, JavaPropsSchema) or settings configurable only through format-mapper builder (CsvMapper.builder().setCSVSpecificThings(123) )
  • Some serializers/deserializers may require direct configuration for exact specifics of Java class in question

But over time it has become clear that there is need for configuring handling of “categories of datatypes” like Date/Time; or “all Enum types”; or “Tree Model” types (JsonNode subtypes); something sort of close to DeserializationFeature / SerializationFeature but not extending to all datatypes.

So Jackson 2.14 now includes a mechanism with which we can easily add:

  • Different kinds of DatatypeFeature implementations (as special kinds of Enums)
  • New entries to said implementations

with very little work within jackson-databind itself: meaning that new kinds of Features and new Feature entries can and will be added incrementally in newer version.

Jackson 2.14 starts with a small set of features, and the expectation is that many more options will be added with later minor versions.
Initially included we have just 2 new options:

  • JsonNodeFeature.READ_NULL_PROPERTIES (databind#3421)— whether null values from incoming JSON will result in NullNode entries being added in ObjectNode (enabled) or not (disabled)
  • JsonNodeFeature.WRITE_NULL_PROPERTIES (databind#3476)— whether NullNode valued entries of ObjectNode will be written out as JSON nulls (enabled) or skipped (disabled)

and configuration will use the standard idiom of:

// May configure ObjectMapper default settings:
ObjectMapper mapper = JsonMapper.builder()
.disable(JsonNodeFeature.READ_NULL_PROPERTIES)
.build();
// and/or change for ObjectReaders/-Writers
JsonNode rootNode = mapper.readerFor(JsonNode.class)
.enable(JsonNodeFeature.READ_NULL_PROPERTIES)
.readValue(inputJson);
String json = mapper.writer()
.disable(JsonNodeFeature.WRITE_NULL_PROPERTIES)
.writeValueAsString(rootNode);

Same will be true for other DatatypeFeatures added — like EnumFeature (which may even still be added in 2.14 if I have time to) or DateTimeFeature (which is highly requested but may need to wait until 2.15).

The main benefit is really for Jackson development team as it will be trivially easy to quickly add new configuration options. There is also minimal overhead for storing these configuration settings (they are backed by bit fields, similar to all other XxxFeature options)

Feature: JsonNode.withObject(JsonPointer) / .withArray(JsonPointer)

JsonNode doc = mapper.readTree(docSource);
// From {"users: [
// { "name" : "Bob", "age" : 42 }
// ])
int age = doc.at("/users/0/age").asInt();

but so far it has not been possible to easily MODIFY Tree Model — based documents.

But Jackson 2.14 adds two new methods (see [databind#1980]) to change this:

  1. JsonNode.withObject(JsonPointer) — will traverse specified path and ensure that at its end there will be a JSON Object (ObjectNode), which is returned
  2. JsonNode.withArray(JsonPointer) — will traverse specific path and ensure that at its end there will be a JSON Array (ArrayNode), which is returned

(as well as 2 overloads for more configurability wrt. what overwrites of existing nodes are allowed)

These methods will allow usage where JsonPointer can be used to indicate Path that either exists OR — if not — WILL exist (that is, be created). So we could construct document like above with:

ObjectNode root = mapper.createObjectNode();
root.withObject(JsonPointer.compile("/users/0")).put("age", 42);

as well as replace existing value(s).

Other Modules

But of special note is Jackson Scala module which has its own release notes:

That’s All, Folks!

--

--

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
@cowtowncoder

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