JSON allows us to express fields that shouldn't be there and fields that could have a null value. These are different things. In Java with cannot have missing fields, so we use null to represent both of these states. We're interoping with an external non-Java party that has a schema like this:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"nullProp": { "type": [ "string", "null" ] },
"optionalProp": { "type": "string" }
},
"required": [ "nullProp" ]
}
because optionalProp is not listed, it can be omitted from the JSON, but if it exists, it must have a non-null value:
- valid:
{ "nullProp": null, "optionalProp": "my value" }
- valid:
{ "nullProp": null }
- valid:
{ "nullProp": "null value", "optionalProp": "my value" }
- invalid:
{ "nullProp": null, "optionalProp": null } // optionalProp cannot be null
- invalid:
{ } // missing required nullProp
we need to send valid JSON that adheres to the schema (manual tests www.jsonschemavalidator.net)
In Java we represent this with:
class Data {
@Nullable String nullProp;
@Nullable String optionalProp;
}
but the serialization behavior needs to be different for these two fields. We've looked at all the combinations of serializeNulls and @JsonAdapter, but couldn't figure out how to omit the optional field when its null, while keeping the null field there if it's null.
Here's a test we've been trying to pass with no luck:
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import com.google.gson.*;
class OptionalTest {
class Data {
// TODO @JsonAdapter(NullAdapter.class)?
String nullProp;
// TODO @JsonAdapter(OptionalAdapter.class)?
String optionalProp;
}
private Gson gson;
@BeforeEach void setUp() {
gson = new GsonBuilder()
// TODO .serializeNulls()?
// TODO .registerTypeAdapterFactory()?
.create();
}
@Test void bothNull() {
Data data = new Data();
data.nullProp = null;
data.optionalProp = null;
assertEquals("{\"nullProp\":null}", gson.toJson(data));
}
@Test void filledContents() {
Data data = new Data();
data.nullProp = "some";
data.optionalProp = "thing";
assertEquals("{\"nullProp\":\"some\",\"optionalProp\":\"thing\"}", gson.toJson(data));
}
}
JSON allows us to express fields that shouldn't be there and fields that could have a null value. These are different things. In Java with cannot have missing fields, so we use
nullto represent both of these states. We're interoping with an external non-Java party that has a schema like this:{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "nullProp": { "type": [ "string", "null" ] }, "optionalProp": { "type": "string" } }, "required": [ "nullProp" ] }because
optionalPropis not listed, it can be omitted from the JSON, but if it exists, it must have a non-null value:{ "nullProp": null, "optionalProp": "my value" }{ "nullProp": null }{ "nullProp": "null value", "optionalProp": "my value" }{ "nullProp": null, "optionalProp": null }//optionalPropcannot be null{ }// missing requirednullPropwe need to send valid JSON that adheres to the schema (manual tests www.jsonschemavalidator.net)
In Java we represent this with:
but the serialization behavior needs to be different for these two fields. We've looked at all the combinations of
serializeNullsand@JsonAdapter, but couldn't figure out how to omit the optional field when its null, while keeping the null field there if it's null.Here's a test we've been trying to pass with no luck: