Does Gson ignore @JsonAdapter on JsonElement fields?

wei :

I have an object to serialize using Gson:

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

On the top object level, I want Gson to ignore null fields (say, if lastname is null, it should not be serialized).

But in field opaqueData , I want nulls to be serialized since it is supposed to a block of opaque data. So using new GsonBuilder().serializeNulls().create().toJson(user) would not work.

But @JsonAdapter does not work either

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

}

It appears that the adapter is ignored by Gson.

Is this expected behavior? How can make this happen without create an adapter for the whole User class then manually serialize each field?

pirho :

Gson does not bother to adapt its internal data type JsonElement. I do not know if there is any point in since JsonElement kind is the adapted result.

Having a glance at the source code of Gson you can see there two top level methods:

For any object

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

I think it is obvious without copying the rest of the code that above method one has searching & setting of adapters (and querying adapter factories) in its execution path. But then there is also method like:

For JsonElement

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

and for that execution path there is no searching nor setting any adapters as JsonElement is not meant to be adapted anymore.

So when Gson hits any JsonElement it just serializes ti as formatted string and you cannot affect on that wiht any adapter.

If you really need to serialize something like that maybe you could make a wrapper class for the JsonElement, something like:

public class JsonElementWrapper {
    public JsonElement jsonElement;
}

and adjust your TypeAdapter to adapt that to `null``or actual value.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=96657&siteId=1