Skip to content

fix(resolver): allow circular reference placeholders in allOf for Ope… - #4312

Open
jochenberger wants to merge 1 commit into
swagger-api:mainfrom
jochenberger:fix-3858
Open

jochenberger wants to merge 1 commit into
swagger-api:mainfrom
jochenberger:fix-3858

Conversation

@jochenberger

Copy link
Copy Markdown

Description

When resolving OpenAPI 3.1/3.2 definitions with useCircularStructures: false (the default), the dereference strategy runs with circular: 'replace'. Each detected circular reference is replaced by the circularReplacer with a generic ObjectElement that contains only $ref. This is intentional, so the placeholder carries no Schema Object semantics.

The AllOfVisitor then checks allOf.content.every(isSchemaElement). That check rejects the very placeholders the resolver inserted, so any circular reference inside allOf produces TypeError: Elements in allOf must be objects and leaves allOf unmerged.

This PR makes the AllOfVisitor (in both the openapi-3-1-swagger-client and openapi-3-2-swagger-client strategies) accept these circular-reference placeholders: non-semantic ObjectElements containing $ref. They are then merged like any other allOf item. The result is a schema that keeps its $ref alongside its sibling keywords, which matches how the OpenAPI 2.0/3.0 specmap resolver already behaves. Genuinely invalid allOf items (e.g. primitives) are still reported as errors.

Motivation and Context

Fixes #3858
Refs swagger-api/swagger-ui#10583 (same root cause, reported against Swagger UI 5.28.0)

Minimal reproduction from #3858:

openapi: 3.1.0
components:
  schemas:
    First:
      allOf:
        - $ref: '#/components/schemas/Second'
    Second:
      allOf:
        - $ref: '#/components/schemas/Third'
    Third:
      allOf:
        - $ref: '#/components/schemas/Second'

A more realistic case from swagger-ui#10583, a self-referencing schema whose allOf adds constraints:

User:
  type: object
  properties:
    friends:
      type: array
      items:
        allOf:
          - $ref: '#/components/schemas/User'
          - type: object
            required: [id]

Before this change, friends.items stayed as an unmerged allOf and an error was reported. After this change, it resolves to { $ref: '…/User', type: 'object', required: ['id'] } with no errors.

How Has This Been Tested?

Added test/bugs/3858.js. It runs for both OpenAPI 3.1.0 and 3.2.0 and goes through the public API (SwaggerClient.resolve and SwaggerClient.resolveSubtree). The public API is needed here because the existing visitor unit tests use apidom's default circular: 'ignore' mode and never hit the swagger-client circularReplacer.

The tests cover:

  • the cyclic allOf definition from OpenAPI 3.1.0: error when resolving schemas with allOf and circular references #3858, both as a full resolve and as a subtree resolve of each schema: no errors, and allOf is merged;
  • the self-referencing allOf from swagger-ui#10583, full and subtree: no errors, and sibling keywords (type, required) are retained;
  • a negative case: a non-object item in allOf still produces Elements in allOf must be objects.

Without the fix, 12 of the 14 new tests fail. The two negative-case tests pass either way, as intended. With the fix, all 14 pass. The existing resolver test suite and the full unit test suite pass as well.

Screenshots (if appropriate):

N/A. The error shown in the screenshot in #3858 no longer appears.

Types of changes

  • No code changes (changes to documentation, CI, metadata, etc)
  • Dependency changes (any modification to dependencies in package.json)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

…nAPI 3.1/3.2

When resolving with useCircularStructures=false, circular references are
replaced by a generic ObjectElement containing only `$ref` (see
circularReplacer). The AllOfVisitor only accepted SchemaElement items and
therefore reported "Elements in allOf must be objects" for these
placeholders, leaving allOf unmerged.

Accept such placeholders in allOf and merge them like any other item,
which matches the behavior of the OpenAPI 2.0/3.0 specmap resolver.

Refs swagger-api#3858
Refs swagger-api/swagger-ui#10583
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

Successfully merging this pull request may close these issues.

OpenAPI 3.1.0: error when resolving schemas with allOf and circular references

1 participant