Skip to content

Commit 6bf1edc

Browse files
committed
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
1 parent 5cef474 commit 6bf1edc

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonFieldTypeResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ JsonFieldType resolveFieldType(String path, Object payload) {
3838
if (commonType == null) {
3939
commonType = fieldType;
4040
}
41-
else if (fieldType != commonType) {
41+
else if (fieldType != commonType && fieldType != JsonFieldType.NULL) {
4242
return JsonFieldType.VARIES;
4343
}
4444
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonFieldTypeResolverTests.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,73 @@ public void multipleFieldsWithDifferentTypes() throws IOException {
112112
}
113113

114114
@Test
115-
public void nonExistentFieldProducesIllegalArgumentException() throws IOException {
115+
public void multipleFieldsWithDifferentTypesAndSometimesAbsent() throws IOException {
116+
assertThat(
117+
this.fieldTypeResolver.resolveFieldType("a[].id",
118+
createPayload("{\"a\":[{\"id\":1},{\"id\":true}, { }]}")),
119+
equalTo(JsonFieldType.VARIES));
120+
}
121+
122+
@Test
123+
public void multipleFieldsWhenSometimesAbsent() throws IOException {
124+
assertThat(
125+
this.fieldTypeResolver.resolveFieldType("a[].id",
126+
createPayload("{\"a\":[{\"id\":1},{ }]}")),
127+
equalTo(JsonFieldType.NUMBER));
128+
}
129+
130+
@Test
131+
public void multipleFieldsWithDifferentTypesAndSometimesNull() throws IOException {
132+
assertThat(
133+
this.fieldTypeResolver.resolveFieldType("a[].id",
134+
createPayload(
135+
"{\"a\":[{\"id\":1},{\"id\":true}, {\"id\":null}]}")),
136+
equalTo(JsonFieldType.VARIES));
137+
}
138+
139+
@Test
140+
public void multipleFieldsWhenSometimesNull() throws IOException {
141+
assertThat(
142+
this.fieldTypeResolver.resolveFieldType("a[].id",
143+
createPayload("{\"a\":[{\"id\":1},{\"id\":null}]}")),
144+
equalTo(JsonFieldType.NUMBER));
145+
}
146+
147+
@Test
148+
public void multipleFieldsWhenEitherNullOrAbsent() throws IOException {
149+
assertThat(
150+
this.fieldTypeResolver.resolveFieldType("a[].id",
151+
createPayload("{\"a\":[{},{\"id\":null}]}")),
152+
equalTo(JsonFieldType.NULL));
153+
}
154+
155+
@Test
156+
public void multipleFieldsThatAreAllNull() throws IOException {
157+
assertThat(
158+
this.fieldTypeResolver.resolveFieldType("a[].id",
159+
createPayload("{\"a\":[{\"id\":null},{\"id\":null}]}")),
160+
equalTo(JsonFieldType.NULL));
161+
}
162+
163+
@Test
164+
public void nonExistentSingleFieldProducesFieldDoesNotExistException()
165+
throws IOException {
116166
this.thrownException.expect(FieldDoesNotExistException.class);
117167
this.thrownException.expectMessage(
118168
"The payload does not contain a field with the path 'a.b'");
119169
this.fieldTypeResolver.resolveFieldType("a.b", createPayload("{\"a\":{}}"));
120170
}
121171

172+
@Test
173+
public void nonExistentMultipleFieldsProducesFieldDoesNotExistException()
174+
throws IOException {
175+
this.thrownException.expect(FieldDoesNotExistException.class);
176+
this.thrownException.expectMessage(
177+
"The payload does not contain a field with the path 'a[].b'");
178+
this.fieldTypeResolver.resolveFieldType("a[].b",
179+
createPayload("{\"a\":[{\"c\":1},{\"c\":2}]}"));
180+
}
181+
122182
private void assertFieldType(JsonFieldType expectedType, String jsonValue)
123183
throws IOException {
124184
assertThat(this.fieldTypeResolver.resolveFieldType("field",

0 commit comments

Comments
 (0)