Improve handling of null fields beneath an array
Previously, if an array contained objects where a field was sometimes null and sometimes had a value of a consistent type, the type inferred type was varies. Furthermore, it was not possible for the user to specify a type other than varies as a mismatch would be detected. This commit updates JsonFieldTypeResolver so that, when dealing with an imprecise field path (i.e. a path for a field within an array), null values that don't match the common type for the field are ignored. This produces the following behavior when nulls are involved: - All null fields results in the null type - A mixture of nulls and a particular type results in the particular type - A mixture of nulls and two or more other types results in the varies type Closes gh-398
This commit is contained in:
@@ -38,7 +38,7 @@ class JsonFieldTypeResolver {
|
||||
if (commonType == null) {
|
||||
commonType = fieldType;
|
||||
}
|
||||
else if (fieldType != commonType) {
|
||||
else if (fieldType != commonType && fieldType != JsonFieldType.NULL) {
|
||||
return JsonFieldType.VARIES;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,13 +112,73 @@ public class JsonFieldTypeResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentFieldProducesIllegalArgumentException() throws IOException {
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesAbsent() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType("a[].id",
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":true}, { }]}")),
|
||||
equalTo(JsonFieldType.VARIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesAbsent() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType("a[].id",
|
||||
createPayload("{\"a\":[{\"id\":1},{ }]}")),
|
||||
equalTo(JsonFieldType.NUMBER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesNull() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType("a[].id",
|
||||
createPayload(
|
||||
"{\"a\":[{\"id\":1},{\"id\":true}, {\"id\":null}]}")),
|
||||
equalTo(JsonFieldType.VARIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesNull() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType("a[].id",
|
||||
createPayload("{\"a\":[{\"id\":1},{\"id\":null}]}")),
|
||||
equalTo(JsonFieldType.NUMBER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenEitherNullOrAbsent() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType("a[].id",
|
||||
createPayload("{\"a\":[{},{\"id\":null}]}")),
|
||||
equalTo(JsonFieldType.NULL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsThatAreAllNull() throws IOException {
|
||||
assertThat(
|
||||
this.fieldTypeResolver.resolveFieldType("a[].id",
|
||||
createPayload("{\"a\":[{\"id\":null},{\"id\":null}]}")),
|
||||
equalTo(JsonFieldType.NULL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentSingleFieldProducesFieldDoesNotExistException()
|
||||
throws IOException {
|
||||
this.thrownException.expect(FieldDoesNotExistException.class);
|
||||
this.thrownException.expectMessage(
|
||||
"The payload does not contain a field with the path 'a.b'");
|
||||
this.fieldTypeResolver.resolveFieldType("a.b", createPayload("{\"a\":{}}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentMultipleFieldsProducesFieldDoesNotExistException()
|
||||
throws IOException {
|
||||
this.thrownException.expect(FieldDoesNotExistException.class);
|
||||
this.thrownException.expectMessage(
|
||||
"The payload does not contain a field with the path 'a[].b'");
|
||||
this.fieldTypeResolver.resolveFieldType("a[].b",
|
||||
createPayload("{\"a\":[{\"c\":1},{\"c\":2}]}"));
|
||||
}
|
||||
|
||||
private void assertFieldType(JsonFieldType expectedType, String jsonValue)
|
||||
throws IOException {
|
||||
assertThat(this.fieldTypeResolver.resolveFieldType("field",
|
||||
|
||||
Reference in New Issue
Block a user