question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Generic wrapper for response: questions about combining oneOf and allOf to mimick json-api

See original GitHub issue

I have been using OpenAPI (v3) for my own project, learning it while doing so my problem might be just an oversight or a lack of practice with Swagger/OAS. I have been trying to get all my API response to issue a standard top-level wrapper, mimicking JSON-API specs (not full compliance yet) with “data”, “meta” and “errors”. I used to have the properties defined directly in the response schema, eg

paths:
  [...]
      responses:
              [...]
              schema:
                properties:
                  data:
                    type: string   # whatever payload
                  meta:
                    type: string   # whatever payload

but it means a lot of repetitions and no obvious semantics. So I created a proper schema for the top-level wrappers and, using model composition with the allOf keyword (and a bit of playing around), I got a more meaningful output:

components:
  schemas:
    v1.JsonApi:
      properties:
        data:
          description: ''
          type: object
        meta:
          description: ''
          type: object
        errors:
          description: ''
          type: array
          items:
            $ref: '#/components/schemas/ApiProblem'
      [...]


paths:
  [...]
      responses:
              [...]
              schema:
                allOf:
                  - $ref: '#/components/schemas/v1.JsonApi'
                  - properties:
                      data:
                        type: string  # whatever payload
                      meta:
                        type: string  # whatever payload

The combination makes clear the output is of a JSONAPI schema (and will be validated off it) then ‘overrides’ the properties with the local paylod. So far so good.

But I still get the errors property as part of the JSONAPI schema; as with the specs, both data+meta and errors top-level properties should be mutually exclusive. Finally, I tried to redefined the JSONAPI schema using the oneOf keywords to separate the two groups:

    v3.JsonApi:
      description: A better exclusion of the two groups of properties, usinf oneOf.
      oneOf:
      - properties:
          data:
            description: ''
            type: object
          meta:
            description: ''
            type: object
      - properties:
          errors:
            description: ''
            type: array
            items:
              $ref: '#/components/schemas/ApiProblem'
      type: object

paths:
  [...]
      responses:
              [...]
              schema:
                allOf:
                  - $ref: '#/components/schemas/v3.JsonApi'
                  - properties:
                      data:
                        type: string  # whatever payload
                      meta:
                        type: string  # whatever payload

But this time, it is not working: it is valid but the output is wrong (in swaggerUI or Hub, both in example and model).

So, three questions really:

  1. Did I miss something is tems of using json-api within OAS? I have checked both GitHub and SO, nothing pertinent.
  2. Am I using allOf properly when combining two schemas to override some of the properties or is this more of an exploit or side effect?
  3. Am I doing something wrong when trying to combine a allOf (in response) with a oneOf (in schema)? Is it just a rendering issue with SwaggerHub or a limitation of the OAS?

I’ve created a wee specs on SwaggerHub if you want to play around.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
elliottpostcommented, Mar 8, 2021

I found @vanch3d’s original post extremely useful, and tried to solve why the example API data would show empty instead of the examples provided. I think it’s because listed above data was set to object but should be array.

Example:

paths:
  '/addresses':
    get:
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/v3.JsonApi'
                  - properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Address"
                      meta:
                        type: object

[...]
components:
  schemas:
    [...]
    v3.JsonApi:
      description: A better exclusion of the two groups of properties, using oneOf.
      oneOf:
        - properties:
            data:
              description: The matching data
              type: array
            meta:
              description: Any relevant metadata
              type: object
        - properties:
            errors:
              description: ''
              type: array
              items:
                $ref: '#/components/schemas/ApiProblem'
      type: object
    Address:
      type: object
      required:
        - id
        - street_1
        - city
        - state
        - postcode
        - country
        - addressable_type
        - addressable_id
        - created_at
        - updated_at
      properties:
        id:
          type: string
          example: "19d0c665-29f1-382a-9d67-37a0fd6a49fa"
        street_1:
          type: string
          example: "123 Main St"
        street_2:
          type: string
          example: "Apt 3"
        city:
          type: string
          example: "Chicago"
        state:
          type: string
          example: "IL"
        postcode:
          type: string
          example: "60660"
        country:
          type: string
          example: "US"
        addressable_type:
          type: string
          example: "business"
        addressable_id:
          type: string
          example: "11b7654f-41b4-3936-822b-d5eebd160d06"
        created_at:
          type: string
          example: "2021-03-07T00:29:36.000000Z"
        updated_at:
          type: string
          example: "2021-03-07T00:29:36.000000Z"
        deleted_at:
          type: string
          example: null

Then, when viewing the generated swagger docs, you can see example data showing in the 200 response preview: Screen Shot 2021-03-08 at 2 18 04 PM

When left to object for data and meta, the example shows: Screen Shot 2021-03-08 at 2 19 28 PM

0reactions
handrewscommented, Feb 24, 2020

Given that this is well over a year old with no further comment, I’m declaring it answered.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Understanding JSON Schema 2020-12 documentation
JSON Schema includes a few keywords for combining schemas together. Note that this doesn't necessarily mean combining schemas from multiple files or JSON ......
Read more >
Solidity Documentation - Read the Docs
Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs.
Read more >
All serialized values are strings, should be integers/booleans ...
Problem/Motivation JSON produced by the HAL and JSON normalizers provides all data values as strings. This makes it difficult for strongly ...
Read more >
GraphQL kinda sucks - Hacker News
This is useful when you are a big company, merging two architectures with different API's together under one umbrella. You can define the...
Read more >
JSON:API — Frequently Asked Questions
Similarly, JSON:API uses IDs for linkage, which makes it possible to cache documents from compound responses and then limit subsequent requests to only...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found