Skip to content

Description is not allowed for elements containing $ref #1514

Closed

Description

@vincnetas

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
swagger-api/swagger-editor#1184 (comment)

Activity

  1. darrelmiller commented on Mar 19, 2018

    @darrelmiller
    Member

    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.
  2. hkosova commented on Mar 22, 2018

    @hkosova
    Contributor

    Related (or duplicate): #556

  3. avantipande1 commented on Dec 24, 2019

    @avantipande1

    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

  4. greatvovan commented on Oct 30, 2020

    @greatvovan
    Contributor

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

  5. LikeLakers2 commented on Oct 31, 2020

    @LikeLakers2
    Contributor
    • 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.

  6. greatvovan commented on Oct 31, 2020

    @greatvovan
    Contributor

    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?

  7. LikeLakers2 commented on Oct 31, 2020

    @LikeLakers2
    Contributor

    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.

  8. darrelmiller commented on Oct 31, 2020

    @darrelmiller
    Member

    @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.

  9. LikeLakers2 commented on Oct 31, 2020

    @LikeLakers2
    Contributor

    @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.

  10. darrelmiller commented on Oct 31, 2020

    @darrelmiller
    Member

    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.

  11. LikeLakers2 commented on Oct 31, 2020

    @LikeLakers2
    Contributor

    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.

  12. greatvovan commented on Nov 1, 2020

    @greatvovan
    Contributor

    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?

  13. 9 remaining items

  14. mohamnag commented on Jan 18, 2022

    @mohamnag

    @webron thanks for mentioning this. It is not clear from this issue what the solution and outcome was. it is not also clear for me by just looking at current spec of 3.1 (https://spec.openapis.org/oas/v3.1.0) how this is solved. I can only see there is a "Reference Object" that can contain description and summary beside $ref however as this object does not replace a "Schema Object" with $ref, I can not see how this is solving mentioned problem in general.

    for example given following sample:

    components:
      schemas:
        SomeSchemaDef:
          type: object
          properties:
            someProp:
              $ref: '#/components/schemas/SomeOtherSchemaDef'
              # here I would like to add a `description` for `someProp`

    what is the solution that OpenAPI 3.1 provides?

  15. blakew commented on Apr 8, 2022

    @blakew

    Thank you for your comment. We've taken it under consideration and implemented it differently in OpenAPI 3.1. We hope you find the solution satisfactory.

    @webron Hi - what is the solution in 3.1?

  16. webron commented on Apr 8, 2022

    @webron
    Member

    @blakew you can use description alongside $ref.

  17. blakew commented on Apr 8, 2022

    @blakew

    Within schemas you can only use $ref and not reference objects. The docs note this distinction:

    Note that this restriction on additional properties is a difference between Reference Objects and Schema Objects that contain a $ref keyword.

    I'm particularly interested in a solution for including descriptions within schemas.

  18. webron commented on Apr 8, 2022

    @webron
    Member

    Correct. Technically you can create and use your own JSON Schema vocabulary that will also allow it in schemas as well.

  19. jdesrosiers commented on Apr 10, 2022

    @jdesrosiers
    Contributor

    @blakew The JSON Schema dialect used in OpenAPI 3.1 is based on JSON Schema 2020-12 which does allow you to put a description (or anything else) alongside $ref. You are correct that $ref in JSON Schema this is not the same as a Reference Object in OpenAPI. There is a significant difference in the way that they work, but they will appear to work the same in most cases. In OpenAPI, the description in the Reference Object will override the description in the referenced object (if there is one). In JSON Schema, there is no overriding. The description in both schemas apply to the instance. However, in the case of keywords like description that don't affect validation results, implementations such as documentation generators are allowed to choose one description if given multiple.

  20. Xbloud commented on Apr 21, 2022

    @Xbloud

    I am not sure I understand the difference between object reference and object schema. Can I include custom properties - extensions - next to the $ref? For example:

    components:
      schemas:
        SomeSchemaDef:
          type: object
          properties:
            someProp:
              $ref: '#/components/schemas/SomeOtherSchemaDef'
              # here I would like to add 'x-my-extension' for 'someProp'
    
  21. jdesrosiers commented on Apr 21, 2022

    @jdesrosiers
    Contributor

    A "Schema Object" is what the documentation calls any part of an OpenAPI document that represents a JSON Schema such as /components/schemas/SomeSchemaDef. The references ($ref) in a "Schema Object" are JSON Schema references and not OpenAPI references. An OpenAPI reference (also $ref) is called a "Reference Object" and covers any references that aren't in a "Schema Object".

    So, in your example, yes, you can add any additional keywords you like next to $ref because it's in a "Schema Object". You don't even need the x- if you don't want to.

  22. michaelcilibrasi commented on Jan 17, 2023

    @michaelcilibrasi

    I didn't follow this tread, it got fragmented quickly. What's the bottom line for:

        location:
          description: User home address location  <- error
          $ref: "#/components/schemas/Location"
    

    Is there a workaround?

  23. hkosova commented on Jan 18, 2023

    @hkosova
    Contributor

    @michaelcilibrasi your example works in OpenAPI 3.1.

    In earlier versions, you need to wrap the $ref into allOf:

        location:
          description: User home address location  <- error
          allOf:
            - $ref: "#/components/schemas/Location"
  24. michaelcilibrasi commented on Jun 29, 2023

    @michaelcilibrasi

    hkosova, I forgot to thank you for your response.

  25. Kostadin-Ivanov commented on Jul 21, 2023

    @Kostadin-Ivanov

    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 swagger-api/swagger-editor#1184 (comment)

    It would be very handy so if we can prepare some defined structure, lets say a responseBody, and then in each API request,
    we just $ref the responseBody and, somehow :), below add list of fields/entries with some example value, which then can be populated in the defined responseBody.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions