Skip to content

Rewrite external discriminator.mapping URIs when bundling #173

Description

@RonnyPfannschmidt

Context

Follow-up from #155.

#155 asked for discriminator.mapping values to be inlined like $ref nodes. That is not valid OpenAPI: the Discriminator Object types mapping as Map[string, string] (schema name or URI reference). Replacing those strings with Schema objects fails validation (as the #155 reporter found when trying a local patch).

Internal fragment refs such as #/components/schemas/Foo should remain strings. Leaving them alone during ResolvingParser inlining is correct.

The real gap is bundling / external URI rewrite: when mapping values point at external files (or relative paths), those strings can become dangling after $ref targets are pulled into components, while adjacent oneOf/anyOf $refs are rewritten or inlined.

This matches the problem space Redocly addressed in redocly-cli#1602 / PR #1666: rewrite mapping strings to local #/components/schemas/... (or equivalent), do not inline schema objects into mapping.

Expected Behaviour

When resolving/bundling a multi-file spec, discriminator.mapping URI values that refer to external (or relative) schemas should be rewritten to stable local string references that still point at the bundled targets.

Minimal Example Spec

openapi: 3.0.3
info:
  title: Discriminator bundling
  version: 1.0.0
paths:
  /pets:
    get:
      responses:
        '200':
          description: ok
          content:
            application/json:
              schema:
                $ref: ./pet.yaml

pet.yaml:

oneOf:
  - $ref: ./cat.yaml
  - $ref: ./dog.yaml
discriminator:
  propertyName: petType
  mapping:
    cat: ./cat.yaml
    dog: ./dog.yaml

After bundling (illustrative), mapping values should be rewritten to local component URIs/names, e.g.:

mapping:
  cat: '#/components/schemas/cat'
  dog: '#/components/schemas/dog'

…not replaced with inlined Schema objects.

Actual Behaviour

reference_iterator / RefResolver only discover JSON Reference objects ({"$ref": "..."}). Bare strings under discriminator.mapping are ignored, so external/relative mapping URIs are left unchanged even when the referenced schemas are bundled elsewhere.

Proposed Solutions

  1. String→string rewrite (preferred for bundling)

    • Discover URI-form values under discriminator.mapping (and optionally schema-name form left alone).
    • Resolve each URI with the same base-URL process as $ref (OAS recommends the $ref process for URI-form mapping).
    • Ensure the target schema is present under components.schemas (same as other bundled externals).
    • Replace the mapping value with a local string such as #/components/schemas/<name> (or a component name, if that is the chosen bundling convention).
    • Keep post-resolve validation enabled; mapping values must remain strings.
  2. Align with existing TRANSLATE_EXTERNAL

    • Today TRANSLATE_EXTERNAL rewrites external $ref sites into local component $refs.
    • Extend that mode (or a dedicated bundling path) so discriminator.mapping URI strings get the same rewrite treatment.
  3. Do not

    • Inline Schema objects into mapping.
    • Change behaviour for already-valid internal #/components/... mapping strings unless a rename/collision policy requires updating them.

Acceptance Criteria

  • External/relative discriminator.mapping URIs are rewritten to local string refs when bundling/resolving multi-file specs.
  • Mapping values remain strings; resolved specs still validate with openapi-spec-validator.
  • Adjacent oneOf/anyOf $ref resolution continues to work as today.
  • Internal-only mapping fragments (as in References in discriminator mappings are not being expanded #155) remain valid string refs without being inlined.
  • Tests cover URI-form mapping rewrite and reject/regression-guard against schema-object inlining.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions