17
17
package org .springframework .restdocs .payload ;
18
18
19
19
import java .io .IOException ;
20
- import java .util .ArrayList ;
20
+ import java .util .Collections ;
21
21
import java .util .List ;
22
+ import java .util .Map ;
22
23
import java .util .Set ;
24
+ import java .util .stream .Collectors ;
23
25
24
26
import com .fasterxml .jackson .databind .ObjectMapper ;
25
27
import com .fasterxml .jackson .databind .SerializationFeature ;
@@ -71,28 +73,39 @@ protected FieldPathPayloadSubsectionExtractor(String fieldPath, String subsectio
71
73
72
74
@ Override
73
75
public byte [] extractSubsection (byte [] payload , MediaType contentType ) {
76
+ return extractSubsection (payload , contentType , Collections .emptyList ());
77
+ }
78
+
79
+ @ Override
80
+ public byte [] extractSubsection (byte [] payload , MediaType contentType , List <FieldDescriptor > descriptors ) {
74
81
try {
75
82
ExtractedField extractedField = new JsonFieldProcessor ().extract (this .fieldPath ,
76
83
objectMapper .readValue (payload , Object .class ));
77
84
Object value = extractedField .getValue ();
78
85
if (value == ExtractedField .ABSENT ) {
79
86
throw new PayloadHandlingException (this .fieldPath + " does not identify a section of the payload" );
80
87
}
88
+ Map <JsonFieldPath , FieldDescriptor > descriptorsByPath = descriptors .stream ()
89
+ .collect (Collectors .toMap (
90
+ (descriptor ) -> JsonFieldPath .compile (this .fieldPath + "." + descriptor .getPath ()),
91
+ this ::prependFieldPath ));
81
92
if (value instanceof List ) {
82
93
List <?> extractedList = (List <?>) value ;
83
- Set <String > uncommonPaths = JsonFieldPaths .from (extractedList ).getUncommon ();
94
+ JsonContentHandler contentHandler = new JsonContentHandler (payload , descriptorsByPath .values ());
95
+ Set <JsonFieldPath > uncommonPaths = JsonFieldPaths .from (extractedList ).getUncommon ().stream ()
96
+ .map ((path ) -> JsonFieldPath .compile (this .fieldPath + "." + path )).filter ((path ) -> {
97
+ FieldDescriptor descriptorForPath = descriptorsByPath .getOrDefault (path ,
98
+ new FieldDescriptor (path .toString ()));
99
+ return contentHandler .isMissing (descriptorForPath );
100
+ }).collect (Collectors .toSet ());
84
101
if (uncommonPaths .isEmpty ()) {
85
102
value = extractedList .get (0 );
86
103
}
87
104
else {
88
105
String message = this .fieldPath + " identifies multiple sections of "
89
106
+ "the payload and they do not have a common structure. The "
90
- + "following uncommon paths were found: " ;
91
- List <String > prefixedPaths = new ArrayList <>();
92
- for (String uncommonPath : uncommonPaths ) {
93
- prefixedPaths .add (this .fieldPath + "." + uncommonPath );
94
- }
95
- message += prefixedPaths ;
107
+ + "following non-optional uncommon paths were found: " ;
108
+ message += uncommonPaths ;
96
109
throw new PayloadHandlingException (message );
97
110
}
98
111
}
@@ -103,6 +116,14 @@ public byte[] extractSubsection(byte[] payload, MediaType contentType) {
103
116
}
104
117
}
105
118
119
+ private FieldDescriptor prependFieldPath (FieldDescriptor original ) {
120
+ FieldDescriptor prefixed = new FieldDescriptor (this .fieldPath + "." + original .getPath ());
121
+ if (original .isOptional ()) {
122
+ prefixed .optional ();
123
+ }
124
+ return prefixed ;
125
+ }
126
+
106
127
@ Override
107
128
public String getSubsectionId () {
108
129
return this .subsectionId ;
0 commit comments