I want to serialize nulls for a specific field or class.
In GSON, the option serializeNulls() applies to the whole JSON.
Example:
class MainClass {
public String id;
public String name;
public Test test;
}
class Test {
public String name;
public String value;
}
MainClass mainClass = new MainClass();
mainClass.id = "101"
// mainClass has no name.
Test test = new Test();
test.name = "testName";
test.value = null;
mainClass.test = test;
Creating JSON using GSON:
GsonBuilder builder = new GsonBuilder().serializeNulls();
Gson gson = builder.create();
System.out.println(gson.toJson(mainClass));
Current ouput:
{
"id": "101",
"name": null,
"test": {
"name": "testName",
"value": null
}
}
Desired output:
{
"id": "101",
"test": {
"name": "testName",
"value": null
}
}
How to achieve the desired output?
Preferred solution would have the following properties:
Do NOT serialize nulls by default,
Serialize nulls for fields with a specific annotation.
解决方案
I have interface to check when object should be serialized as null:
public interface JsonNullable {
boolean isJsonNull();
}
And the corresponding TypeAdapter (supports write only)
public class JsonNullableAdapter extends TypeAdapter {
final TypeAdapter elementAdapter = new Gson().getAdapter(JsonElement.class);
final TypeAdapter objectAdapter = new Gson().getAdapter(Object.class);
@Override
public void write(JsonWriter out, JsonNullable value) throws IOException {
if (value == null || value.isJsonNull()) {
//if the writer was not allowed to write null values
//do it only for this field
if (!out.getSerializeNulls()) {
out.setSerializeNulls(true);
out.nullValue();
out.setSerializeNulls(false);
} else {
out.nullValue();
}
} else {
JsonElement tree = objectAdapter.toJsonTree(value);
elementAdapter.write(out, tree);
}
}
@Override
public JsonNullable read(JsonReader in) throws IOException {
return null;
}
}
Use it as follows:
public class Foo implements JsonNullable {
@Override
public boolean isJsonNull() {
// You decide
}
}
In the class where Foo value should be serialized as null. Note that foo value itself must be not null, otherwise custom adapter annotation will be ignored.
public class Bar {
@JsonAdapter(JsonNullableAdapter.class)
public Foo foo = new Foo();
}