Search code examples
javajsonserializationjodd

Jodd: Not To Serialize Empty Object


Currently we are using JODD lib to do the JSON serialization. But it always serialize the empty object. I want object non-empty object to be serialized to a Json string. How can we do that?

Expecting:
{payload={app={id=xxx, version=0, hash=asdf, riskData={}}}}
--->
{"payload":{"app":{"id":"xxx","version":0,"hash":"asdf"}}} // not to show riskdata.

We are using JsonSerializer in Jodd 3.7.1. Any help?

The scenario we are using Jodd is that we are trying to serialize an embedded log map object.

/* inside this Map, there could be several embedded objects. */
/* ie. {payload={app={id=xxx, version=0, hash=asdf, riskData={}}}} */
Map<String, Object> log; 

As this Map is deserialized from a JSON String, we can't use any annotations to label empty fields. We want to use JsonSerializer to serialize this Map object to a JSON string and exclude any field with empty values, such as empty map (riskData) or an empty list.

I dig into the code yesterday. And found a possible solution, that is to extends the default JsonSerializers such as:

public class NonEmptyMapSerializer extends MapJsonSerializer {
    @Override
    public void serializeValue(JsonContext jsonContext, Map<?, ?> map) {
        // If Map is empty. Skip it.
        if (map.isEmpty()) return;
        super.serializeValue(jsonContext, map);
    }
}
/*-----When initiating a JsonSerializer-----*/
logAllSerializer = new JsonSerializer().withSerializer(Map.class, new NonEmptyMapSerializer());

Same for other types.

Is this solution correct? Will it cause any unexpected behaviors? Or could you provide other better solutions? I can find an Option: .excludeNulls(true) but that only exclude NULL field. Is there an hidden option to 'excludeEmpty'?

Thanks so much!


Solution

  • For null values there is already a excludeNulls flag:

    String json = new JsonSerializer().excludeNulls(true).serialize(map);
    

    This one will ignore all null values.

    The new flag (just committed) is for empty values: excludeEmpty(). It can be used as you expect:

    json = new JsonSerializer().excludeNulls(true).excludeEmpty(true).serialize(map);
    

    Finally, you can have more control using new callback, for example:

    json = new JsonSerializer().excludeNulls(true).onValue(value -> {
            if (value instanceof Map) {
                if (((Map)value).isEmpty()) {
                    return new EmptyJsonSerializer();
                }
            }
            return null;
        }).serialize(map);