Skip to content

[Feature request]: Add API to change schema ID #3707

@bkoelman

Description

@bkoelman

Is your feature request related to a specific problem? Or an existing feature?

In our codebase, in some scenarios, a constructed System.Type is not sufficient to determine a unique schema ID. To make that fit the existing Swashbuckle SchemaGenerator API, we:

  1. Let Swashbuckle generate the schema using SchemaGenerator
  2. Rename the generated schema ID, based on an additional string value

The rename happens by obtaining the generated schema from SchemaRepository, removing it and then adding it under a different ID. However, we also need to update the private _reservedIds field for that to work, which we currently do using reflection.

Describe the solution you'd like

I'd like to propose a new method on SchemaRepository to rename the schema ID for an existing System.Type.

public void ReplaceSchemaId(Type oldSchemaType, string newSchemaId);

The implementation would resemble what we currently use:

private static readonly FieldInfo ReservedIdsField; // loaded via reflection

public static void ReplaceSchemaId(this SchemaRepository schemaRepository,
    Type oldSchemaType, string newSchemaId)
{
    ArgumentNullException.ThrowIfNull(schemaRepository);
    ArgumentNullException.ThrowIfNull(oldSchemaType);
    ArgumentException.ThrowIfNullOrEmpty(newSchemaId);

    if (schemaRepository.TryLookupByType(oldSchemaType, out OpenApiSchemaReference? referenceSchema))
    {
        string oldSchemaId = referenceSchema.Reference.Id!;

        IOpenApiSchema targetSchema = schemaRepository.Schemas[oldSchemaId];

        schemaRepository.Schemas.Remove(oldSchemaId);
        schemaRepository.Schemas.Add(newSchemaId, targetSchema);

        var reservedIds = (Dictionary<Type, string>)ReservedIdsField.GetValue(schemaRepository)!;
        reservedIds.Remove(oldSchemaType);
    }
}

Although we don't need it, it may be better to return a boolean indicating whether the replacement has happened.

Once approved, I'm willing to open a PR to implement this.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions