Jackson 2.10 feature: JsonNode improvements
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:
- 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 - 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:
require()
andrequireNonNull()
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 methodspath()
orat()
)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 byrequire()
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)