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

Parser ignore readOnly/writeOnly on property with $ref #2036

Closed
rongli-mx opened this issue Jan 12, 2024 · 5 comments
Closed

Parser ignore readOnly/writeOnly on property with $ref #2036

rongli-mx opened this issue Jan 12, 2024 · 5 comments

Comments

@rongli-mx
Copy link

The Parser ignore the readOnly attribute on the property Order.customer

openapi: "3.0.1"
info:
  title: test
  version: "1.0"

paths:

  /ping:
    get:
      operationId: ping
      responses:
        200:
          description: OK
  /order:
    get:
      operationId: getOrder
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
    put:
      operationId: putOrder
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Order'
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: string

components:
  schemas:
    Customer:
      type: object
      properties: 
        id:
          type: string
        name:
          type: string
    Order:
      type: object
      properties:
        id:
          type: string
        operations:
          type: array
          items:
            $ref: '#/components/schemas/Operation'
          readOnly: true
        customer:
          $ref: '#/components/schemas/Customer'
#          readOnly: true # readOnly here will be ignored
    Operation:
      type: object
      properties:
        id:
          type: string
        status:
          type: string
          readOnly: true
        name:
          type: string
          writeOnly: true
          readOnly: false
@Felk
Copy link

Felk commented Dec 6, 2024

I believe this issue extends to more than just readOnly when using $ref, as I am experiencing a very similar issue with title and description.

The issue seems to be the way the OpenAPIDeserializer handles refs:

JsonNode ref = node.get("$ref");
if (ref != null) {
    if (ref.getNodeType().equals(JsonNodeType.STRING)) {
        // ...
        return schema; // uh-oh!
    } else {
        result.invalidType(location, "$ref", "string", node);
        return null;
    }
}

getCommonSchemaFields(node, location, result, schema);

Here, if a ref is found, the ref is resolved and then the schema is returned as-is. The following steps -- most notably getCommonSchemaFields which reads such fields as title, description or readOnly -- get skipped.

@Felk
Copy link

Felk commented Dec 6, 2024

This might actually be intended behaviour, because the OpenAPI 3.1 specification states this for ref objects:

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

For proper composition, this OpenAPI construct should do the trick instead:

    Order:
      type: object
      properties:
        id:
          type: string
        operations:
          type: array
          items:
            $ref: '#/components/schemas/Operation'
          readOnly: true
        customer:
          allOf:
            - $ref: '#/components/schemas/Customer'
          readOnly: true # readOnly should not be lost anymore

@Felk
Copy link

Felk commented Dec 9, 2024

I've gotten some clarifications in smallrye/smallrye-open-api#2097 (comment) and as I now understand, the mentioned schema should work in OpenAPI 3.1, because the Schema object now is defined as just being JSON Schema draft 2020-12. And within that I found this (section 8.2.3.1: Direct References with "$ref", emphasis mine)

The "$ref" keyword is an applicator that is used to reference a
statically identified schema. Its results are the results of the
referenced schema. [[CREF5: Note that this definition of how the
results are determined means that other keywords can appear alongside
of "$ref" in the same schema object
. ]]

I also found an example in the spec that does the same (section 7.7.1.1: )

         ...
         {
             "title": "Feature A",
             "properties": {
                 "enabled": {
                     "$ref": "#/$defs/enabledToggle",
                     "default": true
                 }
             }
         },
         {
             "title": "Feature B",
             "properties": {
                 "enabled": {
                     "description": "If set to null, Feature B
                                     inherits the enabled
                                     value from Feature A",
                     "$ref": "#/$defs/enabledToggle"
                 }
             }
         }
         ...

So as far as I understand, this is a valid use-case and should be supported in OpenAPI 3.1, especially since this appears to be how e.g. smallrye-openapi generates all refs now.

@frantuma
Copy link
Member

Swagger Parser correctly allows siblings for $ref within a schema according to OAS 3.1 spec (not allowed in 3.0.1). Please update your example above to set openapi to 3.1.0 and this will work as expected

@Felk
Copy link

Felk commented Dec 12, 2024

Hey, thanks for clarifying! I was under the impression that I did test with OpenAPI 3.1, but I just checked and indeed I didn't, sorry for that 🙏 turns out the issue I'm facing is actually an issue in openapi-generator, not in the swagger-parser: OpenAPITools/openapi-generator#20304

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

3 participants