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 null
s 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?
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.