Skip to content

feat: support override attributes and type placeholders in .swaggo#2148

Open
isasmendiagus wants to merge 1 commit intoswaggo:masterfrom
isasmendiagus:feat/override-attrs
Open

feat: support override attributes and type placeholders in .swaggo#2148
isasmendiagus wants to merge 1 commit intoswaggo:masterfrom
isasmendiagus:feat/override-attrs

Conversation

@isasmendiagus
Copy link
Copy Markdown

@isasmendiagus isasmendiagus commented Mar 11, 2026

Summary

  • Add key:value attribute syntax to .swaggo replace directives (nullable, optional, format)
  • Add $T type parameter placeholder for generic catch-all overrides
  • Introduce Override struct to replace raw string type mappings

Closes #2147
Closes #1852

Changes

  • parser.goOverride struct, matchOverride(), getOverrideForType(), applyOverrideAttrs(), updated getTypeSchema() and parseStructField()
  • gen/gen.goparseOverrides() with key:value attribute parsing
  • parser_test.go — new tests for nullable, format, placeholder, and matchOverride
  • gen/gen_test.go — new test cases for attrs, format, malformed input, and placeholder
  • generics_test.go — updated to use Override struct

Usage

// Primitives with attributes
replace common.Optional[string] string optional:true nullable:true
replace common.Optional[time.Time] string optional:true nullable:true format:date-time

// Generic catch-all
replace common.Optional[$T] $T optional:true nullable:true

Add structured Override type to replace raw string overrides, enabling
nullable, format, and other schema attributes to be specified alongside
the type name when overriding generic placeholders (e.g. $T).

Key changes:
- Override struct with Type, Nullable, and Format fields
- matchOverride() for comparing type names against overrides
- getOverrideForType() to find matching overrides for a given type
- applyOverrideAttrs() to apply nullable/format attributes to schemas
- parseOverrides() in gen.go with key:value attribute parsing syntax
- Comprehensive tests for all new functionality
@maxclaus
Copy link
Copy Markdown
Contributor

maxclaus commented Mar 24, 2026

@sdghchj could you please check this one out when you have some time? It would be a great addition to the tool, being able to handle generic wrapper types globally is something a lot of codebases need.

I tested locally on my project and confirmed it works great. Here's a concrete example of what it unlocks.

Context: we use a tri-state optional.Value[T] wrapper for PATCH endpoints (absent / null / present), since Go's JSON marshaller does not distinguish null from absent (undefined) fields.

Before, we had to maintain a parallel *Doc struct purely for swagger:

// PatchRequestPayloadDoc is a doc-only type used to generate correct swagger output.
// It mirrors PatchRequestPayload but replaces optional.Value[T] with *T.
type PatchRequestPayloadDoc struct {
    Date             *int64            `json:"date"`
    Status           *domain.Status    `json:"status"`
} // @name PatchRequestPayload

type PatchRequestPayload struct {
    Date             optional.Value[int64]            `json:"date,omitempty"`
    Status           optional.Value[domain.Status]    `json:"status,omitempty"`
}

...
// @Param body body PatchRequestPayloadDoc true "Patch payload"

After, with a single line in .swaggo:

replace optional.Value[$T] $T nullable:true

The real struct is used directly in the annotation, no duplicate needed:

type PatchRequestPayload struct {
    Date             optional.Value[int64]            `json:"date,omitempty"`
    Status           optional.Value[domain.Status]    `json:"status,omitempty"`
}

...
// @Param body body PatchRequestPayload true "Patch payload"

Generated output renders each field as its inner type with x-nullable: true, exactly correct. Zero optional.Value-* intermediate definitions in the spec.

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.

Support attributes (nullable, format, optional) and type placeholders in .swaggo overrides Support swagger type format for global override

2 participants