Openapi-specification: Description is not allowed for elements containing $ref

Created on 19 Mar 2018  路  16Comments  路  Source: OAI/OpenAPI-Specification

I know that specification says that when using $ref any other elements are ignored.
So here a real life scenario.

    location:
      description: User home address location  <- error
      $ref: "#/components/schemas/Location"
    carLocation:
      description: Where user has left his car  <- error
      $ref: "#/components/schemas/Location"

So if i have same structure of location but different semantics, only way to communicate this would be through field names, but that is very limiting.
Also two locations could be created with identical structure, just to distinguish between semantics, but this is code duplication.

I understand that this is not a trivial issue, but this is obvious shortcoming in spec which i noticed after just couple of days of basic real life usage... And i'm not the only one.

There are people with the same problem here
https://github.com/swagger-api/swagger-editor/issues/1184#issuecomment-323070576

Most helpful comment

There are few points regarding this:

  • This is a design choice that the OpenAPI specification inherited from JSON Schema. The JSON Schema folks are working on trying to find a solution to this issue. That would be the best place to have this conversation.
  • This is what appears at first to be a simple issue and then upon deeper inspection it becomes a non-trivial issue to resolve all the possible conflicts arising from merging two overlapping schemas. This is an issue that has been discussed literally for years.
  • The allOf operator can be used to define one schema to define the local properties, e.g. description and another schema with the $ref. It doesn't solve all scenarios and it is not the most concise syntax but it can work.
  • This can also be resolved by modelling the relationship between the user and the car as an object. So, the user object has a car object that has a location property. This has the added benefit of being able to attach other properties to the relationship between the user and the car and group those properties together.

All 16 comments

There are few points regarding this:

  • This is a design choice that the OpenAPI specification inherited from JSON Schema. The JSON Schema folks are working on trying to find a solution to this issue. That would be the best place to have this conversation.
  • This is what appears at first to be a simple issue and then upon deeper inspection it becomes a non-trivial issue to resolve all the possible conflicts arising from merging two overlapping schemas. This is an issue that has been discussed literally for years.
  • The allOf operator can be used to define one schema to define the local properties, e.g. description and another schema with the $ref. It doesn't solve all scenarios and it is not the most concise syntax but it can work.
  • This can also be resolved by modelling the relationship between the user and the car as an object. So, the user object has a car object that has a location property. This has the added benefit of being able to attach other properties to the relationship between the user and the car and group those properties together.

I was looking for same use case where I want to add description for the $ref field in swagger. Above answer helped, when we add description with allOf, swagger-ui picks up this description. Now my problem is how to generate allOf programmatically? Is there any annotation that can be used to generate allOf. I am using swagger-maven-plugin with @ApiModel and @ApiModelProperty to generate swagger from APIs.
Any help would be greatly appreciated.
Thank you

This looks like a serious design flaw in both OpenAPI and JSON Schema.

  • This is a design choice that the OpenAPI specification inherited from JSON Schema. The JSON Schema folks are working on trying to find a solution to this issue. That would be the best place to have this conversation.

This part of the comment appears to be out-of-date, it seems? The version of the JSON Schema Core used by 3.1.0-RC1 does not seem to explicitly disallow additional properties being beside $ref, as seen at the example in section 7.7.1.1, although that same section does appear to note that "The application programmer and the schema author need to agree on the usage" in regards to this. (I might be misunderstanding this, though)

Additionally, within the changelog for that version of JSON Schema Core, there is this note:

  • Allow keywords adjacent to "$ref"

which would also support that keywords can be used next to the $ref property. However, OpenAPI still disallows additional properties next to $ref fields, except for summary and description. I will also note section 7.2 here, as it seems to regard this very issue (though maybe I'm misunderstanding section 7.2 about this?).

If I might suggest something -- perhaps specification extensions could be allowed next to $ref properties, so long as they are about the Reference Object itself? I can provide an example of what I mean, if you'd like.

If this is off-topic for this issue, I'd be happy to open a new issue regarding this.

Nice research @LikeLakers2, I think it worth opening a new issue as I believe OpenAPI must eventually move towards a graceful resolution of this problem.

Also you write

OpenAPI still disallows additional properties next to $ref fields, except for summary and description.

This page explicitly says that any such properties will be just ignored. In what way does it disallow additional properties?

In what way does it disallow additional properties?

Bad wording on my part. Woops.

Anyways, I'll open an issue soon. And I'll make sure to use the right wording this time, haha.

@LikeLakers2 @greatvovan

In OpenAPI 3.1 you can use any JSON Schema property alongside a $ref in a schema object.

However, $ref used in other OAS objects like parameter, requestBody, can only have summary and description as peers.

JSON Schema has done the hard work to clearly define how peer properties interact with $ref. In OpenAPI we are going to have to define the semantics of peer properties on a case by case basis. We have allowed summary and description as they don't impact behavior. We are open to considering other properties but we will need to do that carefully.

Regarding the swagger.io doc, I believe that wording is incorrect. in 3.0 of OAS you are not allowed to include properties alongside $ref, they would cause a validation error.

@darrelmiller That... feels confusing. Why do we have two different definitions for $ref based on what object it's replacing?

Also,

Regarding the swagger.io doc, I believe that wording is incorrect. in 3.0 of OAS you are not allowed to include properties alongside $ref, they would cause a validation error.

If the swagger.io doc is incorrect, then the specification itself should be updated.

In the Reference Object documentation for both v3.0.3 and v3.1.0-RC1, and even on v3.1.0 on the development branch (as of the time of this comment), the following text is found regarding additional properties:

This object cannot be extended with additional properties and any properties added SHALL be ignored.

The use of the word "ignore" here would imply that additional properties (including specification extensions) can be in the object, but will never be parsed. If that isn't what is meant, then the wording in the specification should be fixed.

This object cannot be extended with additional properties and any properties added SHALL be ignored.

My mistake. I thought the spec explicitly disallowed those properties.

Why do we have two different definitions for $ref based on what object it's replacing?

We have the OAS Reference object and JSON schema has a $ref object. We use the same keyword because they have approximately the same behavior. This is the impact of enabling full JSON Schema support. JSON Schema is able to identify every property as either an annotation or a constraint. It has defined how annotations and constraints can be combined. Every property in JSON schema can be evaluated independently. In OAS the relationships between properties is more complex. Allowing arbitrary inclusion of peer properties to a $ref could create some very confusing situations.

e.g. Here's just one example

paths:
   '/{foo}':
     parameters:
        - $ref: #/components/parameters/foo
           in: path

components:
  parameters:
     foo:
       in: query
       required: false
       schema:
         type: string

foo is not required, but path parameters are. Therefore we need to define if this reuse is allowed, and what that means for the required property. I suspect there are a dozens more examples like this. Not impossible to resolve, but will take time and add complexity.

My mistake. I thought the spec explicitly disallowed those properties.

The wording is admittedly a bit vague -- I can see why it might trip you up, even if you knew it said that. It says "cannot be extended" only to say that additional properties will "be ignored". "Cannot be extended" would imply that you are disallowed from even including them, whereas "be ignored" would imply that you can include them if you don't mind the parser ignoring them. However, both of them being in reference to how an object can be structured, means that the actual meaning might be vague -- and parsers will probably take the least restrictive route, just-in-case.

So I think it may be worth clarifying this wording anyways... maybe replace the line with something like "Any additional properties (including specification extensions) SHALL be ignored."

[example]

Ah, I think I understand the difference now. Thanks. I can see why that might be hard to deal with.

Is there any active issue regarding trying to figure that out?


As an aside, it may be worth clarifying that $ref in Schema Objects is different than $ref in Reference Objects. I notice that this is already done in the Reference Objects section, but it may be worth including such a thing under the Schema Objects section too -- especially for people like me who would be transitioning from 3.0 to 3.1.

I have a question about wording here:

If the referenced object-type does not define a description (summary) field, then this field has no effect.

Does it mean that if the schema object by the reference does not have a description but the Reference object has description, then the "resulting" object will not anyway have description? If so, why? Why can't it just ADD-OR-OVERRIDE the field?

@greatvovan OAS Reference Objects are no longer used by Schema Objects in OAS. The comment quoted above is only used for other components. e.g If you $ref a Response Object and put a "summary" property in the Reference Object it will be ignored because Response Object does not have a summary property.

We don't want to be in a position where allowing a property in a Reference Object implicitly means it can be added to any other component.

Got it.

Maybe rephrase it then as "does not allow" instead of "does not define"?

Maybe rephrase it then as "does not allow" instead of "does not define"?

Might be an improvement. PR welcome!

@darrelmiller I saw you gave a thumbs up to my comment -- do you want me to open a PR to make those suggested changes?

Was this page helpful?
0 / 5 - 0 ratings