Gson 会忽略 JsonElement 字段上的 @JsonAdapter 吗?

Does Gson ignore @JsonAdapter on JsonElement fields?

我有一个对象要序列化,使用 Gson:

class User {
    String firstname;
    String lastname;
    JsonElement opaqueData;
}

在顶级对象级别,我希望 Gson 忽略 null 字段(例如,如果 lastnamenull,则不应序列化)。

但是在字段 opaqueData 中,我希望 nulls 被序列化,因为它应该是一个不透明的数据块。所以使用 new GsonBuilder().serializeNulls().create().toJson(user) 是行不通的。

但是@JsonAdapter也不行

class User {
    String firstname;
    String lastname;
    @JsonAdapter(NullAdapter.class)
    JsonElement opaqueData;
}

class NullAdapter extends TypeAdapter<JsonElement> {

    @Override
    public void write(JsonWriter out, JsonElement value) throws IOException {
        out.jsonValue(new GsonBuilder().serializeNulls().create().toJson(value));
    }

    @Override
    public JsonElement read(JsonReader in) throws IOException {
        // TODO Auto-generated method stub
        return null;
    }

}

Gson 似乎忽略了适配器。

这是预期的行为吗?如何在不为整个用户创建适配器的情况下实现这一点 class 然后手动序列化每个字段?

Gson 懒得去适应它的内部数据类型 JsonElement。我不知道是否有任何意义,因为 JsonElement kind 是改编的结果。

看一眼 source code of Gson 您可以看到两个顶级方法:

对于任何对象

public String toJson(Object src) {
    if (src == null) {
        return toJson(JsonNull.INSTANCE);
    }
    return toJson(src, src.getClass());
}

我认为在不复制其余代码的情况下,上述方法一在其执行路径中搜索和设置适配器(以及查询适配器工厂)是显而易见的。但是还有这样的方法:

对于 JsonElement

public String toJson(JsonElement jsonElement) {
    StringWriter writer = new StringWriter();
    toJson(jsonElement, writer);
    return writer.toString();
}

并且对于该执行路径,没有搜索也没有设置任何适配器,因为 JsonElement 不再适用。

因此,当 Gson 命中任何 JsonElement 时,它只是将 ti 序列化为格式化字符串,您无法使用任何适配器影响它。

如果你真的需要序列化类似的东西,也许你可以为 JsonElement 制作一个包装器 class,比如:

public class JsonElementWrapper {
    public JsonElement jsonElement;
}

并调整您的 TypeAdapter 以适应“空”或实际值。