restdocs-api-spec icon indicating copy to clipboard operation
restdocs-api-spec copied to clipboard

support for $ref

Open alexisparis opened this issue 3 years ago • 7 comments

Hi,

I am trying to use rest-docs / restdocs-api-spec to generate the openapi spec for these two endpoints :

the first endpoint returns a list of Driver and the second one just one driver. I didn't found yet a way to document that on my unit test.

So, for now, the generated spec contains, in components/schema, a Driver structure and another structure that represents a list of Driver, but on these two structures, the duplication of code is important :

Is there a way to document things so that something like the following will be generated?

alexisparis avatar Apr 07 '21 19:04 alexisparis

Hey @alexisparis ,

yeah, the schema generation isn't smart enough for this use-case, yet. Would you mind posting the resource.json snippet for each of the two examples, please?

How restdocs-api-spec generates a JSON schema

The common brain is in here: https://github.com/ePages-de/restdocs-api-spec/blob/master/restdocs-api-spec-jsonschema/src/main/kotlin/com/epages/restdocs/apispec/jsonschema/JsonSchemaFromFieldDescriptorsGenerator.kt#L28 (tests: https://github.com/ePages-de/restdocs-api-spec/blob/master/restdocs-api-spec-jsonschema/src/test/kotlin/com/epages/restdocs/apispec/jsonschema/JsonSchemaFromFieldDescriptorsGeneratorTest.kt ) which produces a JSON schema string which is then parsed in the OpenAPI 2, 3 generators to produce the respective schemas (Model type for OpenAPI 2/Swagger 1.5, Schema type for OpenAPI 3), e.g.: https://github.com/ePages-de/restdocs-api-spec/blob/master/restdocs-api-spec-openapi-generator/src/main/kotlin/com/epages/restdocs/apispec/openapi2/OpenApi20Generator.kt#L461 https://github.com/ePages-de/restdocs-api-spec/blob/master/restdocs-api-spec-openapi3-generator/src/main/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3Generator.kt#L371

Roughly speaking, two payloads produce the same JSON schema, if both are of the same content type and use the same set of FieldDescriptors (two descriptors considered the same, if they document the same JSON path). In the generators we then keep a cache of JSON schemas (map with Model/Schema types as key) and reuse a schema if some payload produces the same Model/Schema (using the equality defined by those upstream classes of the Swagger project). Notice how this isn't attempting in finding common reusable sub-structures. So far, it mostly works for when request and response payloads match (common resource) and thus the same set of FieldDescriptors apply, producing the same schema, which is then defined once and referenced for both cases. The only "smartness" I see there right now, is type unification (two FieldDescriptors for same path, but with different types, produce a schema for a single field supporting the union of both types).

The reason I'm asking for your resource.json snippets is, that maybe we could try to use subsectionWithPath or some prefix for the array and then have a common set of descriptors (all with same paths) across both responses, which might produce the same schema (I'm uncertain here, but prob. worth a try).

ozscheyge avatar Apr 07 '21 21:04 ozscheyge

@ozscheyge thank you for your support resource-get-driver.log resource-get-drivers.log

alexisparis avatar Apr 08 '21 17:04 alexisparis

Okay, the produced resource.json files confirm my assumption:

Single resource:

      "path" : "dangerous",

Collection resource:

      "path" : "[]dangerous",

etc. So, as explained above, the basic algorithm to form the schema from the FieldDescriptors does not detect that those paths may describe the same object.

ozscheyge avatar Apr 08 '21 17:04 ozscheyge

Hi @ozscheyge I made some tries with subsectionWithPath but was not able to generate spec as expected. Is there a way to provide a reference type? Do you know how subsectionWithPath should be used in that case?

alexisparis avatar Apr 12 '21 12:04 alexisparis

Hi @ozscheyge I made some tries with subsectionWithPath but was not able to generate spec as expected. Is there a way to provide a reference type? Do you know how subsectionWithPath should be used in that case?

Hey, the subsectionWithPath-suggestion was just an ad-hoc idea, seems like it didn't work. :| I'm afraid, this issue isn't supported by restdocs-api-spec, yet.

ozscheyge avatar Apr 12 '21 19:04 ozscheyge

@ozscheyge Hi, I also need this part. If I get a chance in the future, can I modify the code a bit to utilize 'AbstractDescriptor.attributes()' and submit a pull request? I don't think it would be a small cost to work on this part, and furthermore, I don't think using 'AbstractDescriptor.attributes()' would be the right way to do it, so I need consent.

xeromank avatar Sep 04 '23 08:09 xeromank

Hey @xeromank ,

what would be the right way to do this, in your opinion? Could you outline, how you would solve this using AbstractDescriptor.attributes(), please?

ozscheyge avatar Sep 04 '23 14:09 ozscheyge