Skip to content

Jackson3 Changes JsonNode

Tatu Saloranta edited this page Nov 9, 2018 · 14 revisions

Jackson 3 changes: JsonNode

Configurability

As of Jackson 2.x, only some of DeserializationFeatures (and few if any SerializationFeatures) affect handling of JsonNode. This is due to most of them being POJO-centric, as JsonNode is meant to be faithful representation of JSON that was read, or is to be written out, with few changes.

But users do have legitimate need/desire to make SOME changes. It's just that these changes are not necessarily aligned with changes to POJO handling.

With that, I suggest addition of...

NodeFeature

This would be enumeration like DeserializationFeature with choices like:

  • READ_NULL_PROPERTIES (default: true) -- are null valued properties represented as NullNodes in resulting JsonObject or skipped?
  • WRITE_NULL_PROPERTIES (default: true) -- are null valued fields in ObjectNode written out as JSON or skipped?
  • READ_NULL_ELEMENTS (default: true) -- are null elements in JSON arrays represented as NullNodes in resulting JsonArray or skipped?
  • WRITE_NULL_ELEMENTS (default: true) -- are null elements in ArrayNode written out as JSON or skipped?
  • CONVERT_POJOS_FULLY (default: ?) -- when converting values (mapper.convertValue(), treeToValue()), are opaque values contained in POJONode:
    1. Serialized explicitly by matching serializer (true) -- which will essentially transform it into non-opaque value (like Map, List etc)
    2. Written out as "writePOJO", which in case of TokenBuffer will retain opaque value exactly as is

One thing to note is that while there could be NodeReadFeature/NodeWriteFeature, I think set of values we need is small enough, and things closely related so that it makes more sense to have just one set. It is also bit easier to implement.

Opportunities from JsonMapper.shared()

As per

https://github.com/FasterXML/jackson-databind/issues/2176

there is finally a globally shared "default" ObjectMapper available, and this allows some things that were not formerly available:

  1. JsonNode.toString() can use real, non-duplicated, full serialization functionality!
    • before this change, I was planning to actually remove ability altogether since output of 2.x is NOT guaranteed to be valid JSON, and much of functionality from mapper-originated serialization (ObjectMapper.writeValueAsString() is simply not available -- and cost of instantiating mapper (or heaven help, ThreadLocal...) is too expensive for such usage
    • but now toString() can just return JsonMapper.shared().writeValueAsString()
    • also see section about exception reporting: we will be able to allow full error reporting, too

Exception reporting

With 3.0, plan is to change JsonProcessingException to be unchecked:

This is relevant for JsonNode, too, since we can start throwing formal Jackson exceptions, without having to declare them separately for all (or just some) accessors. This is relevant for a few entries here:

  • JsonNode.toString() can pass any exceptions for real serializationn as-is, with no additional wrapping

However: I think it also makes sense to introduce at least one new Jackson exception type, like:

  • ValueCoercionException

which can then be used by methods that attempt coercion (like JsonNode.asIntValue()), but fail due to incompatible types (or perhaps parsing error, from String to number). This exception type should retain and expose information like:

  • Source token type (JsonToken.VALUE_STRING)
  • Target shape (as token, like JsonToken.VALUE_NUMBER_INT)
  • If available, target Java type (java.lang.Integer#type for int, for example)
  • We do not necessarily have information on path, but possibly exception catch/rethrow could re-create this

Clone this wiki locally