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

What is consistent way to define property accepting object defined by $ref? #1060

Closed
meteozond opened this issue Oct 10, 2019 · 4 comments
Closed

Comments

@meteozond
Copy link

We've got requirement to pass response content objects as values for our properties, and looks like it is legal and describing it using $ref looks like reasonable idea.

But it isn't clear from the specs how it should be done and looks like we've got several approaches here.

Using allOf

  • Defining allOf array with two items:
    • field level properties (for example title and other),
    • nested object schema difinition $ref
{
    "properties":
        {
            "property": {
                "allOf": [
                    {
                        "title": "Dependence property title",
                        "description": "Dependence property description"
                    },
                    {
                        "$ref": "#/components/schemas/Dependence"
                    }
                ]
            }
        }
}

allOf jsfidle example

And redoc rendered schema will be:

Screen Shot 2019-10-10 at 16 05 03

I don't like this aproach because we say that the property

accepts some object wich schema is the result of merging two these schemas.

And redoc doesn't show property title.

Using anyOf

  • Defining anyOf array with nested object schema difinition $ref as only value.
  • Defining property title and other attrs on the property level.
{
    "properties":
    {
        "property": {
            "title": "Dependence property title",
            "description": "Dependence property description",
            "anyOf": [
                {
                    "$ref": "#/components/schemas/Dependence"
                }
            ]
        }
    }
}

anyOf jsfidle example

And redoc rendered schema will be:

Screen Shot 2019-10-10 at 16 30 34

I don't like this aproach because

anyOf as the $ref notations have to override the object structure where it used.

So my queestion is - What is consistent way to define properties with $ref values?

@RomanHotsiy
Copy link
Member

"property": {
  "title": "Dependence property title",
  "description": "Dependence property description",
  "allOf": [
    {
      "$ref": "#/components/schemas/Dependence"
    }
  ],
}

@meteozond
Copy link
Author

@RomanHotsiy wow, thanks. Is there any motivation behind this solution? Is it a best practice?

@RomanHotsiy
Copy link
Member

Well, here are some technical and semantic differences.

First, it is important to understand what allOf and anyOf means. From JSON Schema, allOf means that the value should be valid agains all of the schemas from allOf while anyOf means to any of the schemas from allOf. So, semantically allOf is somehow similar to merge (while not exactly) while anyOf is kind of boolean or operator.

I just thought and using allOf with just one subschema and anyOf with one subschema is technically the same but it has different semantics (if extrapolate to more than one subschema case). That's why the common practice is using allOf when you need something similar to merge and overwrite some keywords kind of behaviour.

Now, why title is not shown in the first example. This is not a bug in Redoc and is an intended behaviour.

Merging two schemas doesn't imply the resulting schema will have one of the subschemas title, e.g.:

{
    "properties":
        {
            "property": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Cat"
                    },
                    {
                        "$ref": "#/components/schemas/Dog"
                    }
                ]
            }
        }
}

The resulting schema title is neither Cat nor Dog so Redoc doesn't merge titles for allOf. BUT when the title is on the same level as allOf it is an explicit way to name the resulting schema:

{
    "properties":
        {
            "property": {
                "title": "Pet",
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Cat"
                    },
                    {
                        "$ref": "#/components/schemas/Dog"
                    }
                ]
            }
        }
}

I hope this makes sense.

@meteozond
Copy link
Author

@RomanHotsiy It's clear now. Thanks a lot!

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

No branches or pull requests

2 participants