Jackson 2.10 feature: JsonNode improvements

@cowtowncoder
3 min readNov 6, 2019

--

Handling of JsonNode (base class of Tree Model representation in Jackson) was significantly improved in Jackson 2.10 as mentioned in “Jackson 2.10 features” overview. But due to space constraints overview did not dig very deep. Let’s have another look at what was added.

JsonNode.toString() is now supported

Although users sometimes used toString() implementation of JsonNode values, this was actually not supported usage by Jackson. Usage was unsupported because it was implemented so that:

  1. Serialization did not go through ObjectMapper but relied on separate simplified String concatenation that was only meant for troubleshooting and specifically did NOT guarantee valid JSON output: character escaping (for example) was not done properly for Object keys or String values
  2. Writing as JSON-like output was implemented inefficiently so using it for large documents would be wasteful as well as possibly incorrect.

Jackson 2.10 fixes both issue(see databind issue #2187 for details) so usage is now fully supported. Serialization uses ObjectMapper with default settings, so does not allow alternate configuration with one exception: there isJsonNode.toPrettyString() method that produces “pretty-printed” JSON (one with indentation).
So if you want to change output aspects you will still want to use writeValue() (and related) methods in ObjectMapper or ObjectWriter.
But toString() will work well for error reporting, diagnostics and logging use cases, and may be convenient for unit test usage.

JsonNode is now java.io.Serializable

Although JsonNode values are naturally serializable — that is, just write out as JSON — some frameworks (such as Spark, Flink and Hadoop) use JDK Serializability for transferring configuration objects, and sometimes even data (although for data it is typically not a good choice).

Jackson 2.10 finally resolves databind issue #18 and makes Object and Array nodes (and their contents) serializable via ObjectOutputStream / ObjectInputStream. So while passing JSON as JSON is generally preferable, it is now possible to transfer JsonNode instances wherever basic JDK serialization mechanism is used.

Convenient Validating Traversal methods for JsonNode

After working on refactoring test code that uses Jackson’s JsonNode for verifying correctness of REST API request and response payloads, I came to miss ability to use “validating” accessors: methods that will access or traverse Tree hierarchy, but also verify assertions while doing this.

Details of this can be seen in databind issue #2237 but the basic idea is that a few “requireXxx()” and “requiredXxx()” methods were added to help combine traversal and assertions, to simplify code like:

JsonNode root = ...;
JsonNode value = root.path("data").path("x");
if (value.isMissingNode()) {
throw new IllegalArgumentException("No value /data/x");
}
int x = value.asInt();

to instead use:

int x = root.requiredAt("/data/x").asInt();
// or, for longer
x = root.path("data").path("x").require();

Which for content like

{ "data" : {
"x" : 42
}}

would return 42 but for content like

{ "data" : {
"value" : 42
}}

would throw a descriptive IllegalArgumentException indicating missing value at specified path.

Methods added can be divided in two main groups:

  1. require() and requireNonNull() that operate on node itself, to ensure that it is not a “missing node” (placeholder), resulting from path in a Tree Model that does not exist (when using methods path() or at())
  2. required(String) (for Object nodes), required(int) (for Array nodes), requiredAt(JsonPointer) (for arbitrary paths through Objects and/or Arrays), that are short-hand combinations of traversal followed by require() on result node

For full descriptions, see Jackson 2.10 JsonNode Javadocs.

These are just first additions: it is easy to see how further specializations could be useful; and there is JSTEP-3 plan focused on additions that may be done in Jackson 3.0 to support Optional return values as alternative to “missing node” approach. So if you think of good additions that would further improve ergonomics, feel free to file an issue at jackson-databind issue tracker to suggest additions in 2.11 (or 3.0)

--

--

@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