乔德:不要序列化空对象

Jodd: Not To Serialize Empty Object

目前我们正在使用 JODD 库进行 JSON 序列化。但它总是序列化空对象。我希望将对象非空对象序列化为 Json 字符串。我们该怎么做?

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

我们在 Jodd 3.7.1 中使用 JsonSerializer。 有帮助吗?

我们使用 Jodd 的场景是我们正在尝试序列化一个嵌入式日志映射对象。

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

由于此 Map 是从 JSON 字符串反序列化的,因此我们不能使用任何注释来标记空字段。 我们想使用 JsonSerializer 将此 Map 对象序列化为 JSON 字符串,并排除任何具有空值的字段,例如空地图 (riskData) 或空列表。

我昨天深入研究了代码。并找到了一个可能的解决方案,即扩展默认的 JsonSerializers 例如:

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());

其他类型也一样。

这个解决方案是否正确?它会导致任何意外行为吗?或者你能提供其他更好的解决方案吗? 我可以找到一个选项:.excludeNulls(true) 但它只排除 NULL 字段。 'excludeEmpty'有隐藏选项吗?

非常感谢!

好的,我会 post 我自己的问题的唯一解决方案,因为到目前为止还没有人回应。

对于每种类型的对象 (String/Map/Integer/Iterable...) Jodd 定义了自己的默认序列化程序。例如,对于 Map.class,默认序列化器如下所示:

/**
 * Map serializer.
 */
public class MapJsonSerializer extends KeyValueJsonSerializer<Map<?, ?>> {

    @Override
    public void serializeValue(JsonContext jsonContext, Map<?, ?> map) {
        jsonContext.writeOpenObject(); // In here, it outputs "map-name":{

        int count = 0;

        Path currentPath = jsonContext.getPath();

        for (Map.Entry<?, ?> entry : map.entrySet()) {
            Object key = entry.getKey();
            Object value = entry.getValue();

            count = serializeKeyValue(jsonContext, currentPath, key, value, count); // in here it serialize each key/value pair recursively.
        }

        jsonContext.writeCloseObject(); // in here, it outputs the closing parenthe like '}' to close this map.
    }
}

所以,我的解决方案是创建我们自己的地图序列化程序,它首先检查地图是否为空。如果不为空,则使用默认序列化器对其进行序列化。如果是空的,那么只是 return 根本不显示它。

public class NonEmptyMapSerializer extends MapJsonSerializer {
    @Override
    public void serializeValue(JsonContext jsonContext, Map<?, ?> map) {
        // If Map is empty. Skip it.
        if (map == null) return;
        if (map.isEmpty()) return;
        super.serializeValue(jsonContext, map);
    }
}

希望对您有所帮助!如果您遇到类似问题,这可能是一种可能的解决方案。

对于 null 值,已经有一个 excludeNulls 标志:

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

这个将忽略 所有 null 个值。

新标志(刚刚提交)用于空值:excludeEmpty()。可以如你所愿的使用:

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

最后,您可以使用新的回调进行更多控制,例如:

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