Skip to content
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

Provide a snippet for documenting request and response structure #277

Open
wilkinsona opened this issue Jul 11, 2016 · 9 comments
Open

Provide a snippet for documenting request and response structure #277

wilkinsona opened this issue Jul 11, 2016 · 9 comments
Labels
type: enhancement Enhancement that adds a new feature

Comments

@wilkinsona
Copy link
Member

wilkinsona commented Jul 11, 2016

With complex, heavily nested payloads some people have found the table of fields that's currently produced by the request and response fields snippets a little difficult to use when trying to determine the structure.

A suggestion has been to reflect the nesting in the documentation, ideally with collapsible sections. A relatively simple, albeit without collapsible sections, approach would be something like this:

{
    "userName": String,
    "name": {
        "familyName": String,
        "givenName": "String
    },
    "phoneNumbers": [ {
        "value": String
    } ],
    "emails": [ {
        "value": String,
        "primary": Boolean
    } ],
    "active": Boolean,
    "verified": Boolean,
    "origin": String,
    "externalId": String
}
@wilkinsona wilkinsona added the type: enhancement Enhancement that adds a new feature label Jul 11, 2016
@wilkinsona wilkinsona added this to the 1.2.0.RC1 milestone Jul 11, 2016
@AnnaMaus86
Copy link

We faced the same problem and did the following:

a) Override the response-fields.snippet like:

|===
|Path|Type|Description

{{#fields}}
|{{#tableCellContent}}`{{#displayName}}{{displayName}}{{/displayName}}{{^displayName}}{{path}}{{/displayName}}`{{/tableCellContent}}
|{{#tableCellContent}}`{{type}}`{{/tableCellContent}}
|{{#tableCellContent}}{{description}}{{/tableCellContent}}

{{/fields}}
|===

=> displayName is an optional attribute to override long and ugly paths

b) Use Multiple .andDo(document(....)) calls for each nested structure in a response body like:

MvcResult res = mockMvc.perform(
    RestDocumentationRequestBuilders.post("/search/products")
            .with(myHeader)
            .contentType(myType)
            .content(mapper.writeValueAsString(params)))
            .andExpect(status().isOk())
            .andDo(document("search/prodcuts",
                CliDocumentation.curlRequest(),
                HttpDocumentation.httpRequest(),
                HttpDocumentation.httpResponse(),
                relaxedResponseFields(
fieldWithPath([].metaData").attributes(key("displayName").value("metaData")).description("Product Meta Data"),
fieldWithPath([].content").attributes(key("displayName").value("content")).description("Product Content"))))
            .andDo(document("search/prodcuts/metaData",
                relaxedResponseFields(
fieldWithPath([].metaData.f1").attributes(key("displayName").value("f1")).description("F1 desc..."),
fieldWithPath([].metaData.f2").attributes(key("displayName").value("f2")).description("F2 desc"),
)))
            .andDo(document("search/prodcuts/content",
                relaxedResponseFields(
fieldWithPath([].content.f1").attributes(key("displayName").value("f1")).description("Content F1 desc..."),
fieldWithPath([].content.f2").attributes(key("displayName").value("f2")).description("Content F2 desc"),
)))
            .andReturn();

=> This generates multiple response-fields.adoc files containing simple, clear and reusable tables for a single nested structure.

@AnnaMaus86
Copy link

Note: If my last comment is at the wrong place/issuce feel free to move it :-)

@wilkinsona
Copy link
Member Author

@AnnaMaus86 Interesting approach. Thank you for sharing what you did.

@AnnaMaus86
Copy link

@wilkinsona Note, that we developed this approach to mimic the Github API (like in https://developer.github.com/v3/git/tags/#create-a-tag-object)

@dsyer
Copy link
Member

dsyer commented Oct 10, 2016

I have found that I want to document the existence of the fields (with some brief description) in the table (or something similar), and then make more detailed notes about the content below that, with separate snippets for each subfield that I want to document. This means that I need a new snippet type for an individual response field, something like new ResponseFieldSnippet("foo.bar") to extract the foo.bar field from the response.

The only difficult part for me has been parsing the field specification ("foo.bar" in the example above) and extracting the right parts of the response. Especially difficult when one of the fields traversed is an array because you might want a specific array element and be unwilling to specify it by index (in case the order wasn't deterministic).

A further complication with arrays is that the logical file name for an extracted field snippet is the path used to extract it ("foo.bar" in the example generates "foo.bar.adoc"), but if the path has an array index (e.g. "foo.bar[0]") then you can't include it in Asciidoctor because of the way the include gets parsed. I had to adopt a convention that I stripped out the indexed parts from a path before I generated the file name.

@wilkinsona
Copy link
Member Author

Thanks, @dsyer. That sounds like a use case for another kind of snippet. Could you open another issue please? I'm interested to know what sort of thing you're documenting in the snippet for an individual field and what assertions you think REST Docs could provide for it.

@dsyer
Copy link
Member

dsyer commented Oct 10, 2016

See #312.

@davidgoate
Copy link

davidgoate commented Mar 28, 2018

@wilkinsona you mentioned on #498

not a fan of introspecting a DTO to discover fields and types. It takes any DTO to JSON conversion out of the equation and, if the introspection doesn't use the exact same conversion that your app does at runtime, can lead to inaccurate documentation.

Is there any possibility to use some sort of JSON schema generator https://gist.github.com/mpellegrini/7571845 or https://github.com/FasterXML/jackson-module-jsonSchemain order to generate without having to write introspection code or worry about inconsistencies between introspection and how jackson would serialise.

@wilkinsona
Copy link
Member Author

@davidgoate I'd like to explore what might be possible with JSON schema, but have never had the time. See #43 for the original idea. Offering support for something like Jackson's JSON schema module (for apps using Jackson for serialization) could fit well with that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement Enhancement that adds a new feature
Projects
None yet
Development

No branches or pull requests

4 participants