1

目前我们正在使用 JODD lib 进行 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' 是否有隐藏选项?

非常感谢!

4

2 回答 2

1

好的,我会将我唯一的解决方案发布到我自己的 Q 中,因为到目前为止还没有人回复。

对于每种类型的对象(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.
    }
}

所以,我的解决方案是创建我们自己的 Map 序列化程序,它首先检查地图是否为空。如果不为空,则使用默认的序列化程序对其进行序列化。如果为空,则直接返回而不显示它。

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

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

于 2018-07-20T22:44:26.597 回答
1

对于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);
于 2018-08-13T12:44:22.923 回答