Howard Liu
Howard Liu

Reputation: 93

Is it possible to 'inject' reference to a JSON Schema

Considering I need to refer to a json with the following format:

{
    "data": {
        "type": "ObjectA"
    }
}

When I write JSON schema (or more specifically, schema object of OpenAPI Specification v3.0.3) for this json request, I write

components:
    schemas:
        Data:
            type: object
            required:
                - data
            properties:
                data:
                    $ref: '#components/schemas/ObjectA'
        ObjectA:
            type: object
            properties:
                type:
                    type: string
        ObjectB:
            type: object
            properties:
                type:
                    type: string
                some_properties:
                    type: string

... and I refer to it using $ref: '#components/schemas/Data'.

However now there is the other json to deal with, which is very similar to the one above except that the object in data property is not of type ObjectA, it is ObjectB instead.

{
    "data": {
        "type": "ObjectB",
        "some_properties": "which is different from ObjectA"
    }
}

Is there a way for me to reuse the schemas for Data above without creating a new schema (so it is like injecting #components/schemas/ObjectA or #components/schemas/ObjectB into Data whenever needed)?

I have considered using oneOf but it does not fit since only a specific object is valid for a specific API endpoint (even though all are under the data property) instead of any one of the available objects.

Upvotes: 2

Views: 533

Answers (1)

Carsten
Carsten

Reputation: 2147

In your simple example, it seems unnecessary to re-use the simple Data definition. However, assuming your actual structure is more complex you could combine the general attributes with the specific ones via allOf, e.g.

components:
    schemas:
        BaseData:
            type: object
            required:
                - data
            properties:
                data:
                    type: object
                    properties:
                        type:
                            type: string
                    required:
                        - type
        DataA:
            allOf:
                - $ref: '#components/schemas/BaseData'
                - type: object
                  properties: 
                      data:
                          $ref: '#components/schemas/ObjectA'
        DataB:
            allOf:
                - $ref: '#components/schemas/BaseData'
                - type: object
                  properties: 
                      data:
                          $ref: '#components/schemas/ObjectB'
        ObjectA:
            type: object
            properties:
                type:
                    const: ObjectA
        ObjectB:
            type: object
            properties:
                type:
                    const: ObjectB
                some_properties:
                    type: string
                required:
                    - some_properties

Depending on the actual complexity, the schema might be easier to read/maintain if the shared parts are simply duplicated.

Upvotes: 2

Related Questions