Support documentation of a required field beneath an optional field
Previously, if a field nested beneath an optional field was documented and was required, it would be identified as missing even if its optional ancestor was missing. This made it impossible to document required fields of an optional subsection of a payload. This commit updates JsonContentHandler to consider a field’s ancestors when determining if it should be reported as missing. If the field field has an optional ancestor that is not present, the field is not considered to be missing if it too is not present. If the field has an optional ancestor that is present then the field is considered to be missing if it is not present. Closes gh-429
This commit is contained in:
@@ -52,8 +52,10 @@ class JsonContentHandler implements ContentHandler {
|
||||
List<FieldDescriptor> missingFields = new ArrayList<>();
|
||||
Object payload = readContent();
|
||||
for (FieldDescriptor fieldDescriptor : fieldDescriptors) {
|
||||
if (!fieldDescriptor.isOptional() && !this.fieldProcessor
|
||||
.hasField(fieldDescriptor.getPath(), payload)) {
|
||||
if (!fieldDescriptor.isOptional()
|
||||
&& !this.fieldProcessor.hasField(fieldDescriptor.getPath(), payload)
|
||||
&& !isNestedBeneathMissingOptionalField(fieldDescriptor,
|
||||
fieldDescriptors, payload)) {
|
||||
missingFields.add(fieldDescriptor);
|
||||
}
|
||||
}
|
||||
@@ -61,6 +63,20 @@ class JsonContentHandler implements ContentHandler {
|
||||
return missingFields;
|
||||
}
|
||||
|
||||
private boolean isNestedBeneathMissingOptionalField(FieldDescriptor missing,
|
||||
List<FieldDescriptor> fieldDescriptors, Object payload) {
|
||||
List<FieldDescriptor> candidates = new ArrayList<>(fieldDescriptors);
|
||||
candidates.remove(missing);
|
||||
for (FieldDescriptor candidate : candidates) {
|
||||
if (candidate.isOptional()
|
||||
&& missing.getPath().startsWith(candidate.getPath())
|
||||
&& !this.fieldProcessor.hasField(candidate.getPath(), payload)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUndocumentedContent(List<FieldDescriptor> fieldDescriptors) {
|
||||
Object content = readContent();
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -107,4 +109,42 @@ public class JsonContentHandlerTests {
|
||||
new JsonContentHandler("Non-JSON content".getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentIsConsideredMissing() {
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler(
|
||||
"{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes())
|
||||
.findMissingFields(Arrays.asList(new FieldDescriptor("a"),
|
||||
new FieldDescriptor("b"), new FieldDescriptor("c")));
|
||||
assertThat(missingFields.size(), is(equalTo(1)));
|
||||
assertThat(missingFields.get(0).getPath(), is(equalTo("c")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedOptionalFieldThatIsNotPresentIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler(
|
||||
"{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes()).findMissingFields(
|
||||
Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"),
|
||||
new FieldDescriptor("c").optional()));
|
||||
assertThat(missingFields.size(), is(equalTo(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsPresentIsConsideredMissing() {
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler(
|
||||
"{\"a\":\"alpha\",\"b\":\"bravo\"}".getBytes()).findMissingFields(
|
||||
Arrays.asList(new FieldDescriptor("a").optional(),
|
||||
new FieldDescriptor("b"), new FieldDescriptor("a.c")));
|
||||
assertThat(missingFields.size(), is(equalTo(1)));
|
||||
assertThat(missingFields.get(0).getPath(), is(equalTo("a.c")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsNotPresentIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler(
|
||||
"{\"b\":\"bravo\"}".getBytes()).findMissingFields(
|
||||
Arrays.asList(new FieldDescriptor("a").optional(),
|
||||
new FieldDescriptor("b"), new FieldDescriptor("a.c")));
|
||||
assertThat(missingFields.size(), is(equalTo(0)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user