Expected behavior of JsonInclude.NON_EMPTY with Maps?

682 views
Skip to first unread message

Daniel Halperin

unread,
Aug 1, 2017, 3:02:38 PM8/1/17
to jackson-user
I have an object like this:

class Foo {
   Map<String, String[]> map;
}

using JsonInclude.NON_EMPTY in the default serializer.

Suppose that map = {"key": []}. What is the expected serialization? Should "key": [] be present in the output JSON?

I can see two arguments:
- Option A: map is a property of Foo, but "key" is just part of its value. It's not a property, so "map: {"foo": []}" should appear in the result JSON.
- Option B: JSON doesn't really distinguish Objects and Maps, so we treat both foo.map and map.get("key") as JSON properties. According to NON_EMPTY, "key" should be omitted.

The current behavior is Option B, which I found surprising at first when reading the NON_EMPTY documentation. Wondering if this is a conscious choice and the expected behavior, or a bug, or something else?

Thanks!
Dan

Tatu Saloranta

unread,
Aug 1, 2017, 5:14:06 PM8/1/17
to jackson-user
Ok: this is where distinction between `value` and `content` differ,
for Maps (and referential types). I think your question is similar to
one I had when deciding earlier that 2 properties are needed.

Basic `value`, like

@JsonInclude(Include.NON_EMPTY)

would only exclude "map" itself, and only if it has no elements on Java side.
It's, I think, your Option A.

But if adding `content`, like

@JsonInclude(value = Include.NON_EMPTY, content = Include.NON_EMPTY)

serializer should instruct `NON_EMPTY` check for Map values as well,
and in case of empty `List` or array, that element would be excluded;
and then `Map`, too, would be excluded if nothing was output.
And this would achieve Option B I think.

Does this make sense?

Handling gets rather tricky here, partly due to difference between
contents and vlaue itself; and partly since handling of emptiness is
very different between POJOs and Maps.

Further, although ideally `content=Include.NON_EMPTY` SHOULD work for
Collections and Arrays, currently it does not; only `value` is
supported. This does not matter in your use case, but means that
functionality is not fully orthogonal.

-+ Tatu +-
> --
> You received this message because you are subscribed to the Google Groups
> "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jackson-user...@googlegroups.com.
> To post to this group, send email to jackso...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Daniel Halperin

unread,
Aug 1, 2017, 5:17:51 PM8/1/17
to jackson-user
I should add: another surprising behavior for me is the serialization of {"map": {"key": []}} is '{}' when Include.NON_EMPTY is set, presumably because after '"key": []' is omitted from the Map, then 'map' itself is considered empty and omitted.

private static class Foo {
public Map<String, String[]> map = new HashMap<>();
}

@Test
public void testMapFieldWithEmptyValue() throws JsonProcessingException {
Foo foo = new Foo();
foo.map.put("key", new String[0]);
ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(Include.NON_EMPTY);
assertThat(mapper.writeValueAsString(foo), containsString("map"));
}

Daniel Halperin

unread,
Aug 1, 2017, 5:27:35 PM8/1/17
to jackson-user
Ah! This makes good sense: By using .setSerializationInclusion(Include.NON_EMPTY), I had set both content and value to NON_EMPTY and gotten option B.

Using value=NON_EMPTY, content=ALWAYS works as I expected.

Thanks Tatu!

Tatu Saloranta

unread,
Aug 1, 2017, 5:55:44 PM8/1/17
to jackson-user
On Tue, Aug 1, 2017 at 2:27 PM, Daniel Halperin <dan.ha...@gmail.com> wrote:
> Ah! This makes good sense: By using
> .setSerializationInclusion(Include.NON_EMPTY), I had set both content and
> value to NON_EMPTY and gotten option B.

Right: this method was added before separation of two aspects, and had
to be retrofitted either to only apply as `value`, or to set both
`value` and `content`.

> Using value=NON_EMPTY, content=ALWAYS works as I expected.
>
> Thanks Tatu!

No problem; thank you for asking this as I'm sure other users will be
interested in this too.

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