Sorting nested ObjectNode values alphabetically

56 views
Skip to first unread message

mark r

unread,
Jul 25, 2020, 12:16:03 AM7/25/20
to jackson-user
Hello!


I'm trying to serialize an ObjectNode value that contains nested ObjectNode
values. What is the correct way to have Jackson serialize the keys in alphabetical
order? Bear in mind that I don't actually know the structure of the ObjectNodes
before I serialize them; only that they're effectively arbitrarily nested key/value
structures.

I've seen the Stack Overflow answers:

https://stackoverflow.com/questions/27577701/jackson-objectmapper-specify-serialization-order-of-object-properties

... And they're either not relevant to my problem (specifying annotations on
classes used for deserialization when I'm dealing with ObjectNodes I didn't
deserialize), or specify various combinations of the MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,
or SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS flags,
which don't appear to have any effect.

My code essentially looks like this:

```
  fun canonicalize(
    objectNode: ObjectNode,
    outputStream: OutputStream
  ) {
    val mapper = ObjectMapper()
    mapper.configure(SerializationFeature.INDENT_OUTPUT, false)
    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
    mapper.writeValue(outputStream, objectNode)
  }
```

The data written to the output stream does _not_ have the keys sorted
in alphabetical order.

Any help would be appreciated!

Tatu Saloranta

unread,
Jul 26, 2020, 7:05:57 PM7/26/20
to jackson-user
On Fri, Jul 24, 2020 at 9:16 PM mark r <rm....@gmail.com> wrote:
>
> Hello!
>
>
> I'm trying to serialize an ObjectNode value that contains nested ObjectNode
> values. What is the correct way to have Jackson serialize the keys in alphabetical
> order? Bear in mind that I don't actually know the structure of the ObjectNodes
> before I serialize them; only that they're effectively arbitrarily nested key/value
> structures.

Tree model (JsonNode / ObjectNode) is meant to represent JSON content
exactly as-is, with few if
any transformations, and is handled quite differently from POJOs.
As such there is no auto-sorting feature at this point, although there
are some plans to maybe add support:

https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-3

However: you should be able to convert `ObjectNode` into `Map` (or
just `Object` more generally) with

Map<String, Object> map = mapper.treeToValue(node, Map.class);

after which `SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS` should
work on serialization.
So 2-step processing should handle this particular case.

-+ Tatu +-

rm....@gmail.com

unread,
Jul 27, 2020, 4:15:36 AM7/27/20
to Tatu Saloranta, jackso...@googlegroups.com
On 2020-07-26T16:05:44 -0700
Tatu Saloranta <ta...@fasterxml.com> wrote:
>
> Tree model (JsonNode / ObjectNode) is meant to represent JSON content
> exactly as-is, with few if
> any transformations, and is handled quite differently from POJOs.
> As such there is no auto-sorting feature at this point, although there
> are some plans to maybe add support:
>
> https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-3
>
> However: you should be able to convert `ObjectNode` into `Map` (or
> just `Object` more generally) with
>
> Map<String, Object> map = mapper.treeToValue(node, Map.class);
>
> after which `SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS` should
> work on serialization.
> So 2-step processing should handle this particular case.

Hello!

Does `treeToValue` handle nested ObjectNodes? I'm actually implementing
JSON canonicalization [0]. In Jackson right now, serialization without
indentation fulfills all of the requirements of canonicalization except
for the sorting of keys on serialization.

I can certainly walk the entire tree myself, but I'd prefer not to have
to. :)

[0]https://tools.ietf.org/id/draft-rundgren-json-canonicalization-scheme-00.html

--
Mark Raynsford | https://www.io7m.com

Tatu Saloranta

unread,
Jul 27, 2020, 2:19:05 PM7/27/20
to rm....@gmail.com, jackson-user
On Mon, Jul 27, 2020 at 1:15 AM <rm....@gmail.com> wrote:
>
> On 2020-07-26T16:05:44 -0700
> Tatu Saloranta <ta...@fasterxml.com> wrote:
> >
> > Tree model (JsonNode / ObjectNode) is meant to represent JSON content
> > exactly as-is, with few if
> > any transformations, and is handled quite differently from POJOs.
> > As such there is no auto-sorting feature at this point, although there
> > are some plans to maybe add support:
> >
> > https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-3
> >
> > However: you should be able to convert `ObjectNode` into `Map` (or
> > just `Object` more generally) with
> >
> > Map<String, Object> map = mapper.treeToValue(node, Map.class);
> >
> > after which `SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS` should
> > work on serialization.
> > So 2-step processing should handle this particular case.
>
> Hello!
>
> Does `treeToValue` handle nested ObjectNodes? I'm actually implementing

Yes, it should work recursively; it is full "convertValue()" just with
input value restriction.

> JSON canonicalization [0]. In Jackson right now, serialization without
> indentation fulfills all of the requirements of canonicalization except
> for the sorting of keys on serialization.

Ah. It might make sense to file an RFE issue asking for sorting of
ObjectNode entries as this seems like
a legit use case. As I mentioned it is sort of on my radar as wish,
but as part of bunch of other "JsonNode features".
Sometimes a separate issue makes it easier to prioritize such features.

> I can certainly walk the entire tree myself, but I'd prefer not to have
> to. :)

Yes, makes sense.

>
> [0]https://tools.ietf.org/id/draft-rundgren-json-canonicalization-scheme-00.html

-+ Tatu +-
Reply all
Reply to author
Forward
0 new messages