-
Notifications
You must be signed in to change notification settings - Fork 738
responseFields beneathPath does not work with arrays #473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for the detailed reported. The sample response that you have shown contains two fields:
Combining the beneath path and the field path, you are using the following to document the fields:
Neither field exists so REST Docs is correctly failing as two fields that exist have not been documented and an attempt has been made to document two fields that do not exist. I guess what you’d like to be able to do is to use |
Thanks for the response. I had not tried |
@bsb319 I see you've edited your original description. When you did so, did you change
|
@wilkinsona Aw, yes sorry I did edit the initial post to add more details. I also have a typo in the sample response above as "customers" is invalid JSON. Thank you for your help, you have lead me down the following path (detailed below) where I have uncovered what I feel is my issue.
Where The only place that I am finding the PathType get set is by:
I am not able to get the segment to fulfill the isArraySegment or the isWildcardSegment and still be a valid path. Test Code
Test also passes with the following if I manually modify extractedField's type while debugging to PathType.MULTI: Sample Response:
|
We are currently facing the same problem as @bsb319 but we are using Spring Restdocs 1.2.4. Therefore it would be nice if @wilkinsona could give us a hint if this bug will also be solved in this version. |
@gbtec-ingogriebsch This issue's still open. It's yet to be solved in any version. |
@wilkinsona This was clear to me as I wrote the comment. To say it the other way: It would be nice if you would also fix this bug in the 1.2.x branch. :) |
Ah, I understand now. Yes, in all likelihood the fix will be made in both 1.2.x and 2.0.x although I've yet to figure out what the fix should be… |
I'm assuming the open issue means that it still isn't fixed. I'm using 2.0.1.RELEASE. Is there a workaround so I can make this documentation happen? I'm willing to extend the involved classes and make this work, but at this point, I'd like to avoid spending the time to figure out how to do that. Edit: Tried it with 2.0.2.RELEASE with no change. |
Correct.
I'm not aware of one. |
I agree with @bsb319 that the problem is in I'm not sure I understand why the I also experimented with adding a class like I'm willing to submit a pull request. I think the |
I've been looking at the unit tests for Lines 73 to 84 in d46703d
The Looking at With this implemented, a new test for this would be: @Test
@SuppressWarnings("unchecked")
public void __extractSingleElementArraySubsectionOfJsonMap()
throws JsonParseException, JsonMappingException, IOException {
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[0]")
.extractSubsection("{\"a\":[{\"b\":5}]}".getBytes(),
MediaType.APPLICATION_JSON);
Map<String, Object> extracted = new ObjectMapper()
.readValue(extractedPayload, Map.class);
assertThat(extracted.get("b"), is(equalTo((Object) 5)));
} I haven't looked deep enough to know what the effort of implementing this is, but what do you think, @wilkinsona ? |
Thanks for taking a look, @Jeff-Walker. My hope is that this problem can be fixed with a change to |
Understood. That's why wrote it up before making a pull request. For reference, here's a link to my work-around. It's a copy of Since Anyway, even if what I've said doesn't help with the real issue, if there's anything I can do to help, let me know. Also, thanks for this great product. |
It's me again. I ran into a problem with my little work around when I had more than one item in the array. I got package org.springframework.restdocs.payload;
import java.io.IOException;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Copy of {@link FieldPathPayloadSubsectionExtractor} but gets the first element
* of a list, no matter the value of {@link ExtractedField#getType()}.
*
* The original version would only get the first element of the list if the type is {@code PathType.MULTI}
*
* @author Jeff Walker
* @see FieldPathPayloadSubsectionExtractor
* @see FieldPathPayloadSubsectionExtractor#extractSubsection(byte[], MediaType)
*/
public class FieldPathPayloadArraySubsectionExtrator
implements PayloadSubsectionExtractor<FieldPathPayloadArraySubsectionExtrator>
{
private static final ObjectMapper objectMapper = new ObjectMapper();
private final String fieldPath;
private final String subsectionId;
private final Integer index;
public FieldPathPayloadArraySubsectionExtrator(String fieldPath, String subsectionId) {
this(fieldPath, subsectionId, null);
}
public FieldPathPayloadArraySubsectionExtrator(String fieldPath) {
this(fieldPath, "beneath-array-" + fieldPath, null);
}
public FieldPathPayloadArraySubsectionExtrator(String fieldPath, Integer index) {
this(fieldPath, "beneath-array-" + fieldPath, index);
}
public FieldPathPayloadArraySubsectionExtrator(String fieldPath, String subsectionId, Integer index) {
this.fieldPath = fieldPath;
this.subsectionId = subsectionId;
this.index = index;
}
@Override
public byte[] extractSubsection(byte[] payload, MediaType contentType) {
try {
ExtractedField extractedField = new JsonFieldProcessor().extract(
this.getFieldPath(), objectMapper.readValue(payload, Object.class));
Object value = extractedField.getValue();
if (value instanceof List) {
List<?> extractedList = (List<?>) value;
if (extractedList.size() == 1 || index != null) {
value = extractedList.get(index == null ? 0 : index);
}
else {
throw new PayloadHandlingException(this.getFieldPath()
+ " does not uniquely identify a subsection of the payload");
}
}
return objectMapper.writeValueAsBytes(value);
}
catch (IOException ex) {
throw new PayloadHandlingException(ex);
}
}
@Override
public String getSubsectionId() {
return this.subsectionId;
}
/**
* Returns the path of the field that will be extracted.
*
* @return the path of the field
*/
protected String getFieldPath() {
return this.fieldPath;
}
@Override
public FieldPathPayloadArraySubsectionExtrator withSubsectionId(String subsectionId) {
return new FieldPathPayloadArraySubsectionExtrator(this.fieldPath, subsectionId, index);
}
public FieldPathPayloadArraySubsectionExtrator atArrayIndex(int index) {
return new FieldPathPayloadArraySubsectionExtrator(this.fieldPath, subsectionId, index);
}
} |
Thank you for your patience @bsb319, @ingogriebsch, and @Jeff-Walker. I've made some changes in both 1.2.x and master that I believe should fix the problem described here. I would be most grateful if you could try the latest 1.2.6 or 2.0.3 snapshots and let me know if the changes address each of your individual problems. Snapshots are available from https://repo.spring.io/libs-snapshot. |
Ok, I tried it and I think it's working for me, but let me make sure I haven't forgotten what's going on. I have something like:
And:
And I get a snippet that looks like:
Which looks ok to me. It figures out that it's an array and drops the |
Excellent. Thank you. |
Thanks again for taking care of this. What is your current timeline for when this build makes it into milestone/rc/ga? |
I'd like to wait a while longer to give @bsb319 and @ingogriebsch a reasonable chance to try a snapshot. A pencil something in for a week today. |
I have another question, but let me know if this needs to be sent to a new issue. {
"roles": [
{
"key": "1",
"name": "one",
"more": [
{
"id": 1
}
]
},
{
"key": "1",
"name": "one",
"more": []
}
]
} I now have nested arrays. What I do with this: document(snippetName,
responseFields(
beneathPath("roles").withSubsectionId("roles"),
fieldWithPath("key").description("key"),
fieldWithPath("name").description("name"),
subsectionWithPath("more").description("array"))); And, to get another table: document(snippetName,
responseFields(
beneathPath("roles[].more").withSubsectionId("more"),
fieldWithPath("id").description("id"))); This doesn't work like the one above does, I'm forced to put |
Interesting. Please open a new issue and I’ll take a look. |
버전 낮을경우 리스트처리 제대로 안되는 이슈 있었음 : spring-projects/spring-restdocs#473
Using:
Error:
Test Code that causes error:
Test Code that runs but displays unwanted "[]." in generated table
Sample Response:
The text was updated successfully, but these errors were encountered: