Documentation
¶
Overview ¶
Package metadata extracts OpenAPI schema metadata from Go struct field tags.
This package provides parsers for various struct tags that control OpenAPI schema generation. It bridges the gap between Go struct tags and OpenAPI/JSON Schema properties by parsing tag values and converting them to appropriate metadata structures.
Supported Tags ¶
The package supports three categories of tags:
1. OpenAPI Metadata (openapi tag):
- Schema documentation: title, description, format, examples
- Field modifiers: readOnly, writeOnly, deprecated, hidden, required
- Extensions: x-* prefixed custom fields (field or struct level)
- Struct-level only: additionalProperties, nullable (on _ field)
2. Validation Constraints (validate tag):
- Numeric: min, max, gt, gte, lt, lte, multipleOf
- String: pattern, email, url, uuid, etc.
- General: required, enum (oneof)
3. Specialized Tags:
- default: Default values for fields
- requires: Fields that become required when this field is present
Tag Precedence Rules ¶
When tags overlap, the following precedence applies:
1. Format: validate:"email" sets format, openapi:"format=custom" overrides it 2. Required: validate:"required" is source of truth, openapi:"required" can override for docs 3. Hidden: json:"-" hides from JSON, openapi:"hidden" hides from OpenAPI schema only
Best practices:
- Use validate:"required" for actual validation
- Use openapi:"required" only to override docs (e.g., mark optional field as required in docs)
- Use validate:"email" for format, not openapi:"format=email" (unless overriding)
Complete Example ¶
type User struct {
_ struct{} `openapi:"additionalProperties=false,nullable=false"`
ID int `json:"id" openapi:"readOnly,description=Unique identifier"`
Email string `json:"email" validate:"required,email" openapi:"description=User email address,[email protected]"`
Name string `json:"name" validate:"required,min=3" openapi:"description=Full name,examples=John Doe|Jane Smith"`
Age int `json:"age" validate:"min=0,max=150" openapi:"description=User age,examples=25|30|35"`
Status string `json:"status" validate:"oneof=active inactive" openapi:"description=Account status,examples=active|inactive"`
CreditCard string `json:"credit_card,omitempty" requires:"billing_address,cvv"`
BillingAddr string `json:"billing_address,omitempty"`
CVV string `json:"cvv,omitempty" openapi:"writeOnly"`
Internal bool `json:"-" openapi:"hidden"`
LegacyField string `json:"legacy_field,omitempty" openapi:"deprecated"`
}
OpenAPI Tag ¶
The openapi tag controls OpenAPI-specific schema properties:
// Boolean flags (no value needed) openapi:"readOnly" // Field is read-only (e.g., ID, created_at) openapi:"writeOnly" // Field is write-only (e.g., password, secret) openapi:"deprecated" // Field is deprecated openapi:"hidden" // Field excluded from OpenAPI schema (but in JSON) openapi:"required" // Override required status for docs only // Documentation openapi:"title=Field Title" openapi:"description=Detailed description" openapi:"format=date-time" // OpenAPI format (date, date-time, email, uri, uuid, etc.) // Examples (pipe-separated for multiple values) openapi:"examples=value" // Single example openapi:"examples=val1|val2" // Multiple examples // Extensions (must start with x-, valid at both field and struct level) openapi:"x-internal=true,x-category=admin" // Struct-level options (on _ blank identifier field) openapi:"additionalProperties=false" // Disallow additional properties openapi:"nullable=true" // Struct can be null openapi:"additionalProperties=false,x-strict=true" // Can combine with extensions
Validate Tag ¶
The validate tag uses go-playground/validator format and maps to OpenAPI constraints:
validate:"required" -> Required=true, used as source of truth validate:"min=5,max=100" -> Minimum=5, Maximum=100 validate:"gt=0,lt=100" -> ExclusiveMinimum=0, ExclusiveMaximum=100 validate:"email" -> Format="email" (can be overridden by openapi:"format=...") validate:"url" -> Format="uri" validate:"oneof=red green blue" -> Enum=["red","green","blue"]
Note: validate tag is the source of truth for constraints. Use openapi tag only to add documentation metadata or override specific values for documentation purposes.
Default Tag ¶
The default tag sets default values for fields:
default:"value" // String default (no quotes needed)
default:"42" // Number default (parsed as JSON)
default:"true" // Boolean default (parsed as JSON)
default:"[1,2,3]" // Array default (parsed as JSON)
default:"{\"key\":\"value\"}" // Object default (parsed as JSON)
Requires Tag ¶
The requires tag specifies fields that become required when this field is present (JSON Schema dependentRequired keyword):
type Payment struct {
CreditCard string `json:"credit_card" requires:"billing_address,cvv"`
BillingAddress string `json:"billing_address"`
CVV string `json:"cvv"`
}
When credit_card is present, billing_address and cvv become required.
Hidden vs json:"-" ¶
Two ways to hide fields, with different purposes:
json:"-" // Field not serialized to JSON AND hidden from OpenAPI openapi:"hidden" // Field serialized to JSON BUT hidden from OpenAPI schema
Use cases:
- json:"-" → Completely internal fields (never in API responses or docs)
- openapi:"hidden" → Runtime fields that appear in responses but not in documentation
Error Handling ¶
All parsers return descriptive errors that include:
- Field name where the error occurred
- Tag name that failed to parse
- Specific reason for the failure
Example error: "field Email: failed to parse validate tag: invalid email format"
Index ¶
- func ParseDefaultTag(field reflect.StructField, index int, tagValue string) (any, error)
- func ParseOpenAPITag(field reflect.StructField, index int, tagValue string) (any, error)
- func ParseRequiresTag(field reflect.StructField, index int, tagValue string) (any, error)
- func ParseValidateTag(field reflect.StructField, index int, tagValue string) (any, error)
- type DefaultMetadata
- type OpenAPIMetadata
- type RequiresMetadata
- type ValidateMetadata
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseDefaultTag ¶
ParseDefaultTag parses a default tag and returns DefaultMetadata. Tag format: default:"value".
Parses the default value based on the field type:
- Strings: returned as-is (no quotes needed in tag)
- Numbers, booleans, arrays, objects: parsed as JSON (e.g., default:"[1,2,3]" or default:"{\"key\":\"value\"}")
func ParseOpenAPITag ¶
ParseOpenAPITag parses an openapi tag and returns OpenAPIMetadata. Tag format: openapi:"readOnly,writeOnly,deprecated,hidden,required,title=My Title,description=My description,examples=val1|val2|val3,x-custom=value"
This parser: 1. Parses tag format (comma-separated, key=value pairs or flags) 2. Converts string values to proper OpenAPI types (bool for readOnly/writeOnly/deprecated/hidden/required) 3. Converts empty string to true for boolean flags (e.g., "readOnly" -> ReadOnly=true) 4. Routes x-* prefixed keys to Extensions map (OpenAPI spec requirement) 5. Detects struct-level vs field-level based on field name (blank identifier _ = struct-level) 6. Supports pipe-separated examples values: examples=val1|val2|val3
Field-level options (for named fields):
- readOnly -> ReadOnly=true
- writeOnly -> WriteOnly=true
- deprecated -> Deprecated=true
- hidden -> Hidden=true (field excluded from schema properties)
- required -> Required=true (overrides validate:"required" for docs only)
- title=... -> Title="..."
- description=... -> Description="..."
- format=... -> Format="..." (e.g., "date", "date-time", "time", "email", "uri")
- examples=val1|val2|val3 -> Examples=[val1, val2, val3] (pipe-separated values)
Struct-level options (for _ blank identifier field):
- additionalProperties=true/false -> AdditionalProperties=bool
- nullable=true/false -> Nullable=bool
OpenAPI extensions (valid at both field and struct level):
- x-* -> Extensions["x-*"]="..." (MUST start with x-, minimum length 4)
func ParseRequiresTag ¶
ParseRequiresTag parses a requires tag and returns RequiresMetadata. Tag format: requires:"field1,field2,field3"
Parses comma-separated list of field names that become required when this field is present. Empty strings and whitespace are filtered out.
Example:
- requires:"billing_address,cvv" -> Fields=["billing_address", "cvv"]
- requires:"field1" -> Fields=["field1"]
- requires:"" -> Fields=[] (empty, will be ignored)
func ParseValidateTag ¶
ParseValidateTag parses a validate tag in go-playground/validator format and returns ValidateMetadata. Tag format: validate:"required,email,min=5,max=100,pattern=^[a-z]+$"
This parser: 1. Parses go-playground/validator tag format (comma-separated, key=value pairs) 2. Maps validator tags to OpenAPI/JSON Schema constraints 3. Converts string values to proper OpenAPI types (int, float64, bool) 4. Returns error if value cannot be parsed to expected type
Validator tag -> OpenAPI mapping:
- required -> Required=true
- min=N -> Minimum=N (as float64)
- max=N -> Maximum=N (as float64)
- len=N -> Minimum=N, Maximum=N (as float64, sets both to same value)
- email -> Format="email"
- url -> Format="uri"
- pattern=... -> Pattern="..."
- oneof=... -> Enum="[...]"
- etc.
Types ¶
type DefaultMetadata ¶
type DefaultMetadata struct {
Value any // Parsed default value (JSON-compatible types: string, float64, bool, []any, map[string]any)
}
DefaultMetadata represents the default value extracted from the default tag. This is used for both runtime default application (via mapstructure) and OpenAPI schema generation.
type OpenAPIMetadata ¶
type OpenAPIMetadata struct {
// Field-level API contract metadata (not validation constraints)
// OpenAPI v3.0: readOnly, writeOnly, deprecated are booleans
ReadOnly *bool // field is read-only
WriteOnly *bool // field is write-only
Deprecated *bool // field is deprecated
Hidden *bool // field is hidden from schema (not included in properties)
Required *bool // field is required (override for validate:"required")
Title string // title for the schema
Description string // description for the schema
Format string // format for the schema (e.g., "date", "date-time", "time", "email", "uri")
Examples []any // parsed example values
// Struct-level metadata (only valid when used on _ blank identifier field)
AdditionalProperties *bool // allow additional properties (struct-level)
Nullable *bool // struct is nullable (struct-level)
// Extensions are OpenAPI specification extensions (x-* fields).
// Keys must start with "x-" per OpenAPI spec requirement.
Extensions map[string]any
}
OpenAPIMetadata represents OpenAPI-specific schema metadata extracted from the openapi tag. Types match OpenAPI v3.0 specification for schema metadata. This metadata is used to generate OpenAPI schema properties that are not validation constraints but API contract metadata (e.g., readOnly, writeOnly, deprecated, title, description, examples).
When used on a field (not the _ blank identifier), it represents field-level metadata. When used on the _ blank identifier field, it represents struct-level metadata (additionalProperties, nullable).
type RequiresMetadata ¶
type RequiresMetadata struct {
Fields []string // List of field names that become required when this field is present
}
RequiresMetadata represents fields that become required when this field is present. Extracted from the requires tag for OpenAPI schema generation (JSON Schema dependentRequired keyword).
type ValidateMetadata ¶
type ValidateMetadata struct {
// Numeric validation constraints (for number/integer types)
// OpenAPI v3.0: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf are numbers
Minimum *float64 // inclusive minimum value
ExclusiveMinimum *float64 // exclusive minimum value (value must be > exclusiveMinimum)
Maximum *float64 // inclusive maximum value
ExclusiveMaximum *float64 // exclusive maximum value (value must be < exclusiveMaximum)
MultipleOf *float64 // value must be a multiple of this number
// String validation constraints (for string types)
Pattern string // regular expression pattern that string must match
Format string // predefined format for string validation (e.g., "email", "date-time", "uri")
// General validation constraints
Enum []any // parsed enum values
Required *bool // field must be present
}
ValidateMetadata represents validation constraints extracted from the validate tag. Types match OpenAPI v3.0 specification for schema validation constraints. This metadata is used to generate OpenAPI schema constraints by mapping go-playground/validator tags to OpenAPI/JSON Schema keywords.