-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Description
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 }//optionalPropcannot be null - invalid:
{ }// missing requirednullProp
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));
}
}