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

Using allOf: to define composite schemas #1467

Closed
stevendearborn opened this issue Jan 26, 2018 · 10 comments
Closed

Using allOf: to define composite schemas #1467

stevendearborn opened this issue Jan 26, 2018 · 10 comments

Comments

@stevendearborn
Copy link

I would like to understand the extent of using the allOf: construct in OpenAPI; it may be different than what it is defined in JSON schema.

I would like to define a composite schema by re-using two or more independent schema definitions. It seems that once I add more than one definition to the allOf: array, then 1) the resulting object is not rendered in either Swagger Editor or Swagger UI the way I expect it to be, and 2) there are cascading syntax errors in the editor when defining additional OpenAPI objects.

I think the answer is this [for OpenAPI]:

  1. the allOf: construct is limited to take only one schema reference; the "polymorphism examples" supply its best use.
  2. the allOf: construct should not be used to define the schema of a response: use the oneOf: construct to select one schema from several alternatives.

It is #2 that is what I would like to do: to avoid defining intermediate schemas and just "compose" a response given re-useable schema definitions.

Here is an example:
openapi-13.txt

@stevendearborn
Copy link
Author

Here are some screen shots since downloading the file in YAML format strips the comments

screen shot 2018-01-26 at 2 23 07 pm

screen shot 2018-01-26 at 2 22 45 pm

@stevendearborn
Copy link
Author

Here is the file - copy & paste.
allOfExample.txt

@stevendearborn
Copy link
Author

All references in an allOf: array must be objects, not arrays for example.

Still getting some cascading syntax errors.

@stevendearborn
Copy link
Author

All references in an allOf: array must resolve to be objects. The attached example is working as a composite schema definition in both in-line, in the response and the indirect schema definition.
allOfExampleWorking.txt

@handrews
Copy link
Member

@stevendearborn while I cannot address the current tooling situation with OAS, I can talk about where we are trying to go with this in JSON Schema (I am one of the spec editors for that project).

Many OpenAPI difficulties with JSON Schema arise because it is fundamentally a generative use case: The schemas are read to produce documentation or auto-generated code, without an instance being present (they are also used for validation, but that part works fine).

JSON Schema's validation vocabulary is designed for validation. It works because it is applied to an instance and therefore the ambiguities in the schema become unambiguous: whichever interpretation works with that instance is the one to use. And concepts like inheritance and polymorphism aren't involved at all.

draft-08 of JSON Schema is trying to lay the groundwork for more vocabularies beyond Validation and Hyper-Schema. These vocabularies will eventually address the generative use cases directly.

For example, a code generation vocabulary might add a keyword subclassOf. This would not affect validation, but it would be used to decide whether an allOf is intended to represent subclassing (so a code generator should produce multiple classes in a particular inheritance relationship) or mechanical schema composition (so a code generator should just smoosh it all together and generate one class from the resulting combination of schemas.

We haven't gone very far with this idea yet- previously we'd been talking about making restricted profiles of the validation keywords, which is closer to what OpenAPI does now, and it seems like where you're going with this example. But that got very awkward, and just documented assumptions that tools could make. It seems better to use the schemas to inform the tools how to interpret ambiguous situations.

We'll be continuing to focus on this over the next several months, and we're also talking with the OAI technical steering committee about how/when the OpenAPI Specification can make use of more recent JSON Schema drafts.

@stevendearborn
Copy link
Author

Thanks @handrews. I got the example working but I had to read the rules of JSON schema a few times before I understood it. It makes sense. I will clean up this example.

My objective was to specify the schema of a response as a composite of existing ones and without defining an intermediate schema. This is possible and it enables the reuse of existing definitions without bloating the definitions with response-specific ones.

Thank you also for clarifying the purpose of JSON schema beyond validation. It helps to understand the rendering of documentation output in Swagger Editor and UI and also code generation.

@stevendearborn
Copy link
Author

Here is the example that uses composite schema definitions in both request and response bodies.

I should close this since it can be accomplished. It would be a nice example vis-a-vis "alternative schema definition", called "composite schema definition", in the OpenAPI documentation. Should I leave as open for documentation purposes?

CompositeSchemaDefinitionExample.txt

@rhuanbarreto
Copy link

+1 for this feature.

Creating composite schemas would keep the definition DRY.

@DarkWingDuckWing
Copy link

This feature introduces multiple inheritance which comes with the Diamond Problem.
Schema from original post:

Hypermedia:
  title: hypermedia
  type: object
  allOf:
    - $ref: #/components/schemas/MediaMetadata
    - $ref: #/components/schemas/Images
    - $ref: #/components/schemas/Video
    - $ref: #/components/schemas/Tags
    - $ref: #/components/schemas/Reviews

If any one of these referenced schemas contains the same properties we will run into issues.

This can be avoided by explicitly placing each of these references in their own sub-object, making a the Hypermedia class more explicitly a composition of these types.

Hypermedia:
  title: hypermedia
  type: object
    properties:
      mediaMetadata:
         $ref: #/components/schemas/MediaMetadata
      images:
         $ref: #/components/schemas/Images
      video:
         $ref: #/components/schemas/Video
      tags:
         $ref: #/components/schemas/Tags
      reviews:
         $ref: #/components/schemas/Reviews

I'm not voting against this feature with this comment, just making clear the problem that comes along with it. Perhaps having separate operators for composition and inheritance would satisfy more parties, maybe something like allOf and childOf, respectively.

@handrews
Copy link
Member

OP is was satisfied with an answer, and the other requests mentioned should be directed to the JSON Schema project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants