Serialize null return values to empty string and not 'null'

8,535 views
Skip to first unread message

Ian Clegg

unread,
Oct 8, 2012, 12:10:02 PM10/8/12
to dropwiz...@googlegroups.com
Hi,

I have a resource class with a couple of methods that return a 2D array of data. There are occasions where there are 'holes' in the arrays, for example no data is available for a given row/column. In this case I would like the 'hole' to be serialized as an empty string, at the moment it is serialised as the string 'null'.
From a quick google it looks like the best way to do this is by implementing a custom serializer for null values  http://wiki.fasterxml.com/JacksonHowToCustomSerializers and registering this with the ObjectMapper.
However, im little stuck as to the best way to do this? I've tried this in my Service class constructor and also in initialise, but it doesn't seem to be invoke?

this.getJson().getObjectMapper().getSerializerProvider().setNullValueSerializer(new )

has anybody got at advice?

Cheers
Ian

Nick Telford

unread,
Oct 8, 2012, 12:30:44 PM10/8/12
to dropwiz...@googlegroups.com
Is there a reason you can't simply use empty Strings in your array instead of null values to start with? If not, is there a reason you want to use empty Strings in your JSON representation instead of nulls?

I'd suggest aligning the internal representation with the serialized representation over writing custom serializers.
--
Nick Telford

Coda Hale

unread,
Oct 8, 2012, 1:10:34 PM10/8/12
to dropwiz...@googlegroups.com
If you want to register a custom serializer for your representation class, I'd recommend using @JsonSerialize:

@JsonSerialize(using = MyFancySerializer.class)
public class PossiblySparseArray {
  // … etc …
}

This requires a lot less bothering with the internals of Dropwizard's Jackson interactions.

---
Coda Hale
http://codahale.com


Tatu Saloranta

unread,
Oct 8, 2012, 1:23:05 PM10/8/12
to dropwiz...@googlegroups.com
On Mon, Oct 8, 2012 at 10:10 AM, Coda Hale <coda...@gmail.com> wrote:
> If you want to register a custom serializer for your representation class,
> I'd recommend using @JsonSerialize:
>
> @JsonSerialize(using = MyFancySerializer.class)
> public class PossiblySparseArray {
> // … etc …
> }
>
> This requires a lot less bothering with the internals of Dropwizard's
> Jackson interactions.

In addition, just as an FYI, serializers are NOT called when dealing
with nulls. Same is true for deserializers.
This is a historical thing, idea was to simplify
serializers/deserializers so they need not worry about nulls.

-+ Tatu +-

Ian Clegg

unread,
Oct 9, 2012, 5:41:55 AM10/9/12
to dropwiz...@googlegroups.com
Hi Nick,

Perhaps I should clarify ;-) imagine I have a 3x3 array, Object[][] of strings and int's with one null object reference in the middle retrieved from a datastore in Java, such that:
{ "1", "2", 3 },
{  "4", <Null object>, "6" },
{ 7 ,8 , 9 }

At the moment I get this from DropWizard when serialized

[[ "1", "2", 3],
[[ "4", null , "6"],     <-- note the 'null'
[[ 7, 8, 9]]

ECMA Javascript will deserialize that 'null' as a string object with the value "null", which not what was intended - since there was not a string with value "null" in the datastore

Instead I would like to serialize to:

[[ "1", "2", 3],
[[ "4", , "6"],   <-- note the empty string in the middle (when I say empty string I mean literally that, not two double quotes "" ;-)
[[ 7, 8, 9]]

Where the JavaScript object in the array will be 'undefined', which is the JavaScript equivalent to a Java null reference which was there on the server side.
Hope that helps!

Ian

Nick Telford

unread,
Oct 9, 2012, 5:48:59 AM10/9/12
to dropwiz...@googlegroups.com
["4", , "6"] is not valid JSON... If you want to strip out the nulls entirely (e.g. ["4", "6"]) then filter your array before you return it:

List<Object> builder = new ArrayList<Object>(arr.length);
for (Object o : arr) {
  builder.add(o);
}
return builder.toArray();


To be honest, working with an Object[] screams at me that you're probably doing something a bit odd. Are the elements not all Strings?

TL;DR: Resolve the nulls on the server-side, before you serialize the result as a JSON object.

Ian Clegg

unread,
Oct 9, 2012, 5:49:22 AM10/9/12
to dropwiz...@googlegroups.com
So I guess there no straight forward way to set the default null serializer? It would be nice to set this once and not have to decorate my methods to use a custom one

Nick Telford

unread,
Oct 9, 2012, 5:59:43 AM10/9/12
to dropwiz...@googlegroups.com
There is: http://wiki.fasterxml.com/JacksonHowToCustomSerializers (bottom of the page) but I strongly advise against it.

You'll need a reference to the ObjectMapper instance Dropwizard uses; in Dropwizard 0.5.1 and earlier, you can do this, in your Service class:

ObjectMapper mapper = this.getJson().getObjectMapper();

Then follow the instructions in the link above.

Ian Clegg

unread,
Oct 9, 2012, 6:08:32 AM10/9/12
to dropwiz...@googlegroups.com
Thanks Nick,

This specific application returns timeseries data in tabular form, of which there are thousands of timeseries with millions of datapoints, each with a different schema (ie columns) depending on what is being observed. The user specifies the timeseries and the columns and these should be returned as JSON.
It is therefore not possible to know the datatypes being returned until they have been retrieved from the datastore, which I why I opted for an object[][].
What you just pointed out is that ["4", ,"6"] is not valid JSON - this being the case and assuming ["4", null ,"6"] is the correct form then I need to look at the client code - it just needs to be round trippable

You'll have to excuse me a little, since Java is not my first language (i'm usually doing C++)

Ian Clegg

unread,
Oct 9, 2012, 6:15:28 AM10/9/12
to dropwiz...@googlegroups.com
I tried that(see the line in the first post)

protected void initialize(...., Environment environment)
throws Exception {
this.getJson().getObjectMapper().getSerializerProvider().setNullValueSerializer(new NullSerializer);

But the null serializer isn't invoked. Doesnt that getJSON return a new ObjectMapper each time?

Nick Telford

unread,
Oct 9, 2012, 6:28:59 AM10/9/12
to dropwiz...@googlegroups.com
Ahh yes, you need to use a Jackson Module to do this.

In your Service: this.addJacksonModule(new MyNullSerializerModule());

Then you can define a Jackson Module that adds the desired Serializer.

However, I'd suggest looking at your client-server round-trip and assessing whether nulls are feasible first.
Reply all
Reply to author
Forward
0 new messages