yamlvalidator

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

README

yamlvalidator

A flexible, production-ready YAML validation library for Go with support for:

  • Type checking with YAML 1.2 (and optional YAML 1.1) compliance
  • Full JSON Schema validation with draft-04, draft-06, draft-07, 2019-09, and 2020-12 support
  • Custom validators for values and keys
  • Conditional logic (AnyOf, ExactlyOneOf, MutuallyExclusive, Conditions)
  • Detailed error reporting with source context and precise positions
  • Multi-document YAML support
  • Anchor/alias support
  • Unicode and tab handling in error output

Installation

Requires Go 1.24 or newer. CI verifies the minimum supported Go 1.24 line and the current stable Go release. Security-fixed IDNA/Unicode code is kept in an internal third-party snapshot so full idn-hostname/idn-email support does not force consumers onto Go 1.25.

go get github.com/Yakwilik/go-yamlvalidator

Quick Start

package main

import (
    "fmt"
    "regexp"

    v "github.com/Yakwilik/go-yamlvalidator"
    valv "github.com/Yakwilik/go-yamlvalidator/pkg/valuevalidator"
)

func main() {
    schema := &v.FieldSchema{
        Type: v.TypeMap,
        AllowedKeys: map[string]*v.FieldSchema{
            "name": {
                Type:     v.TypeString,
                Required: true,
                Validators: []v.ValueValidator{
                    valv.RegexValidator{
                        Pattern: regexp.MustCompile(`^[a-z][a-z0-9-]*$`),
                        Message: "must be lowercase with dashes",
                    },
                },
            },
            "replicas": {
                Type: v.TypeInt,
                Validators: []v.ValueValidator{
                    valv.RangeValidator{Min: v.Ptr[float64](1), Max: v.Ptr[float64](100)},
                },
            },
        },
    }

    yaml := []byte(`
name: my-app
replicas: 50
`)

    validator := v.NewValidator(schema)
    result := validator.ValidateBytes(yaml)

    if result.HasErrors() {
        fmt.Println(result.FormatAll(true))
    }
}

Schema Definition

Field Schema
type FieldSchema struct {
    // Basic properties
    Type         NodeType   // Expected type (TypeString, TypeInt, etc.)
    AllowedTypes []NodeType // Accept any listed type; takes precedence over Type
    Required     bool       // Field must be present
    Nullable    bool        // Allow null values
    Deprecated  string      // Deprecation message (empty = not deprecated)
    Description string      // Human-readable description
    Default     interface{} // Suggested default; emits warning if omitted, does not mutate input

    // Map-specific
    AllowedKeys          map[string]*FieldSchema // Known keys
    AdditionalProperties *FieldSchema            // Schema for unknown keys
    UnknownKeyPolicy     UnknownKeyPolicy        // How to handle unknown keys
    KeyValidators        []KeyValidator          // Key name validators

    // Sequence-specific
    ItemSchema *FieldSchema // Schema for items
    MinItems   *int
    MaxItems   *int

    // Value validators
    Validators []ValueValidator

    // Inter-field logic
    AnyOf             [][]string        // At least one group must be present
    ExactlyOneOf      []string          // Exactly one field must be present
    MutuallyExclusive []string          // At most one field can be present
    Conditions        []ConditionalRule // Conditional validation
    OneOfRequired     [][]string        // Exactly one field group must be present
    ForbiddenTogether [][]string        // A complete field group is forbidden
    DependentRequired map[string][]string

    // Schema composition
    OneOfSchemas []*FieldSchema // Exactly one schema must match
    AnyOfSchemas []*FieldSchema // At least one schema must match
}
Native schema compilation

For schemas assembled dynamically, prefer CompileFieldSchema over constructing a validator directly. It rejects invalid schema graphs before any YAML is validated: recursive graphs, incompatible map/sequence constraints, invalid min/max bounds, nil validators, bad regexp definitions, invalid inter-field references, and other definition errors.

validator, err := v.CompileFieldSchema(schema)
if err != nil {
    return err
}

NewValidator remains available for backwards compatibility when the schema is already trusted.

Node Types
Type Description
TypeAny Any type; bare maps/sequences are not recursively constrained
TypeNull Null values only
TypeString String values
TypeInt Integer values
TypeFloat Float values (also accepts int)
TypeBool Boolean values
TypeMap Mapping nodes
TypeSequence Sequence/array nodes
Unknown Key Policy
Policy Behavior
UnknownKeyInherit Uses ctx.StrictKeys (default)
UnknownKeyError Unknown keys are errors
UnknownKeyWarn Unknown keys are warnings
UnknownKeyIgnore Unknown keys are ignored

JSON Schema Compilation

CompileJSONSchema compiles a standards-compliant JSON Schema and returns a FieldSchema adapter. Validation is delegated to a full JSON Schema engine; the YAML validator remains responsible for parsing YAML, preserving source positions, resolving YAML aliases/merge keys, converting the YAML value to the JSON data model, and mapping JSON Schema errors back to YAML diagnostics.

Supported dialects:

  • JSON Schema draft-04
  • JSON Schema draft-06
  • JSON Schema draft-07
  • JSON Schema 2019-09
  • JSON Schema 2020-12

An explicit $schema selects the dialect. Without $schema, draft 2020-12 is used by default and can be changed with DefaultDraft.

All keywords implemented by the engine are available, including references and modern applicators such as $ref, $dynamicRef, $defs, $anchor, allOf, anyOf, oneOf, if/then/else, dependentSchemas, unevaluatedProperties, unevaluatedItems, prefixItems, contains, numeric/string/object/array constraints, boolean schemas, annotations, and vocabulary declarations. Unknown extension keywords follow JSON Schema semantics instead of being rejected merely because yamlvalidator does not know them.

schemaJSON, err := os.ReadFile("easyp-config.schema.json")
if err != nil {
    return err
}

schema, err := v.CompileJSONSchema(schemaJSON)
if err != nil {
    return err
}

result := v.NewValidator(schema).ValidateBytes(yamlData)
Compilation options
policy := v.UnknownKeyWarn
schema, err := v.CompileJSONSchemaWithOptions(schemaJSON, v.JSONSchemaCompileOptions{
    SchemaURL:    "https://schemas.example.com/easyp.json",
    DefaultDraft: v.JSONSchemaDraft2020,

    AssertFormat:  true,
    AssertContent: true,
    AssertVocabs:  true,
    RegexpTimeout: 500 * time.Millisecond, // Optional protection for untrusted schemas

    Resources: map[string][]byte{
        "https://schemas.example.com/common.json": commonSchema,
    },

    LoadURL: func(url string) ([]byte, error) {
        return loadSchemaResource(url)
    },

    AdditionalPropertiesFalsePolicy: &policy,
})

Resources preloads an external schema graph without I/O. LoadURL resolves references not already present in that graph. HTTP(S) fetching is deliberately not enabled implicitly.

RegexpTimeout limits one ECMAScript regexp match. The default value 0 preserves unlimited matching for full compatibility; set a positive duration when validating against untrusted schemas.

For advanced JSON Schema extensions, ConfigureCompiler exposes the underlying compiler before resources are added. It can be used to register custom vocabularies, formats, content encodings/media types, or other engine extensions.

schema, err := v.CompileJSONSchemaWithOptions(schemaJSON, v.JSONSchemaCompileOptions{
    ConfigureCompiler: func(c *jsonschema.Compiler) error {
        c.RegisterFormat(&jsonschema.Format{
            Name: "my-format",
            Validate: validateMyFormat,
        })
        return nil
    },
})
Functional JSON Schema extensions

For common extension cases, yamlvalidator exposes its own API so callers do not need to depend directly on the underlying JSON Schema engine.

A custom format is useful for scalar validation and can also validate mapping keys through propertyNames:

schema, err := v.CompileJSONSchemaWithOptions(schemaJSON, v.JSONSchemaCompileOptions{
    AssertFormat: true,
    Formats: []v.JSONSchemaFormat{
        {
            Name: "module-name",
            Validate: func(value any) error {
                name, ok := value.(string)
                if ok && !validModuleName(name) {
                    return fmt.Errorf("invalid module name")
                }
                return nil
            },
        },
    },
})

The schema can then use {"format":"module-name"} or {"propertyNames":{"format":"module-name"}}.

For arbitrary business logic, register a functional custom keyword. The simplest form is literally a validation function receiving the keyword value from the schema and the current instance value:

keyword := v.JSONSchemaKeyword{
    Name: "x-require-property",
    Validate: func(raw, instance any, ctx *v.JSONSchemaKeywordValidationContext) {
        property, ok := raw.(string)
        if !ok {
            ctx.AddError("x-require-property expects a string")
            return
        }
        object, ok := instance.(map[string]any)
        if !ok {
            return
        }

        ctx.MarkPropertyEvaluated(property)
        if _, ok := object[property]; !ok {
            ctx.AddErrorAt([]string{property}, "required by x-require-property")
        }
    },
}

schema, err := v.CompileJSONSchemaWithOptions(schemaJSON, v.JSONSchemaCompileOptions{
    Keywords: []v.JSONSchemaKeyword{keyword},
})

If keyword configuration needs parsing or validation, use Compile instead of Validate; it receives the keyword value once at schema compilation time and returns a JSONSchemaKeywordValidateFunc for subsequent instance validation.

JSONSchemaKeywordValidationContext supports multiple diagnostics through AddError / AddErrorAt and integrates with unevaluatedProperties / unevaluatedItems through MarkPropertyEvaluated / MarkItemEvaluated. Relative issue paths are mapped back to the corresponding YAML line and column, and the keyword name becomes the diagnostic Code.

For a named set of keywords use JSONSchemaVocabulary{URL, Keywords} through JSONSchemaCompileOptions.Vocabularies. First-class functional vocabularies are activated for that compilation automatically. For advanced keywords which introduce subschemas, custom dialect/meta-schema behavior, or direct engine APIs, use ConfigureCompiler and RegisterVocabulary.

Custom keyword validators operate on the JSON data model (map[string]any, []any, json.Number, strings, booleans, null), not on yaml.Node. Treat the supplied instance as read-only; compiled schemas may be reused concurrently, so captured validator state must be concurrency-safe. YAML-specific validation that needs tags/styles/comments should continue to use native ValueValidator / KeyValidator.

Format and content assertions

For 2019-09 and 2020-12, format remains annotation-only unless the schema vocabulary requires assertions or AssertFormat is enabled. The validator supplies stricter implementations for email, hostname, IPv4, duration, URI, URI-reference, URI-template, idn-email, and idn-hostname, and uses an ECMAScript-compatible regexp engine for JSON Schema patterns and regex format validation.

AssertContent enables contentEncoding, contentMediaType, and contentSchema assertions supported by the engine.

YAML to JSON data model

JSON Schema validates the JSON data model. During validation yamlvalidator converts the YAML AST without losing source locations:

  • YAML mappings become JSON objects; mapping keys therefore must be strings.
  • YAML sequences become JSON arrays.
  • YAML integers and finite floating-point values are converted using exact textual numbers rather than float64 round-tripping.
  • YAML hexadecimal, binary, octal, and legacy octal integers are normalized to their mathematical JSON integer value.
  • YAML aliases and merge keys are resolved before JSON Schema validation.
  • YAML .nan and .inf are rejected because JSON has no non-finite numeric values.
  • YAML custom-tagged scalar values are represented as their scalar string value.

Diagnostics preserve the YAML path, line, column, JSON Schema keyword in Code, and originating schema location in SchemaPath.

Conformance

The JSON Schema adapter is exercised in CI against the official JSON-Schema-Test-Suite using the public CompileJSONSchema and YAML validation path:

  • draft-04: 618/618 core tests
  • draft-06: 841/841 core tests
  • draft-07: 929/929 core tests
  • 2019-09: 1261/1261 core tests
  • 2020-12: 1301/1301 core tests
  • total: 4950/4950 core tests

The same public API also passes 3884/3885 official optional tests when JSON string values are represented losslessly through YAML escapes where necessary. The single remaining optional draft-04 case is zeroTerminatedFloats, which intentionally tests host-language numeric type distinctions by expecting JSON 1.0 not to satisfy integer. yamlvalidator follows the engine's mathematical JSON Schema numeric semantics, where an exactly integral numeric value satisfies integer.

Optional coverage includes ECMAScript pattern semantics, email, idn-email, hostname, idn-hostname, duration, URI, URI-reference, URI-template, content assertions, and format-regex validation. Raw YAML still obeys YAML's own character restrictions; code points such as U+0085 or U+FFFF can be supplied through YAML escapes when a JSON Schema format test needs those exact scalar values.

AdditionalPropertiesFalsePolicy is a yamlvalidator presentation option: it can downgrade or suppress a direct additionalProperties: false diagnostic for editor-style workflows. It does not rewrite JSON Schema combinator semantics.

Built-in Validators

Value Validators
// Enum validation
EnumValidator{Allowed: []string{"v1", "v2", "v3"}}

// Regex validation
RegexValidator{
    Pattern: regexp.MustCompile(`^[a-z]+$`),
    Message: "must be lowercase letters",
}

// Numeric range
RangeValidator{Min: v.Ptr[float64](1), Max: v.Ptr[float64](100)}

// Non-empty check
NonEmptyValidator{}

// Length validation
LengthValidator{Min: v.Ptr[int](1), Max: v.Ptr[int](255)}

// URL validation
URLValidator{RequireScheme: true, AllowedSchemes: []string{"http", "https"}}
Key Validators
// Regex key validation
RegexKeyValidator{
    Pattern: regexp.MustCompile(`^[a-z][a-z0-9._-]*$`),
    Message: "invalid key format",
}

// Forbidden keys
ForbiddenKeyValidator{Forbidden: []string{"password", "secret"}}

// Key length
LengthKeyValidator{Min: v.Ptr[int](1), Max: v.Ptr[int](63)}

Inter-field Logic

AnyOf (at least one group)
// Either configFile, OR both host AND port
AnyOf: [][]string{{"configFile"}, {"host", "port"}}
ExactlyOneOf (exactly one field)
// Exactly one of inline/file/url
ExactlyOneOf: []string{"inline", "file", "url"}
MutuallyExclusive (at most one)
// debug and quiet cannot both be present
MutuallyExclusive: []string{"debug", "quiet"}
Conditional Rules
Conditions: []ConditionalRule{
    {
        ConditionField: "type",
        ConditionValue: "external",
        ThenRequired:   []string{"endpoint"},
        ThenForbidden:  []string{"local"},
    },
}

Validation Options

result := validator.ValidateWithOptions(yaml, ValidationContext{
    StrictKeys:     true,  // Unknown keys are errors for native FieldSchema
    StopOnFirst:    false, // Continue after first error
    StrictTypes:    false, // Parse values for native FieldSchema type inference
    YAML11Booleans: false, // Plain YAML 1.1 yes/no/on/off compatibility

    MaxBytes:       2 << 20, // 2 MiB; 0 = unlimited
    MaxDocuments:   10,      // 0 = unlimited
    MaxDepth:       100,     // root value has depth 1; 0 = unlimited
    MaxDiagnostics: 100,     // 0 = unlimited
})
if result.Truncated {
    // MaxDiagnostics was reached.
}

CLI

The CLI supports both the native serialized FieldSchema format and standards-compliant JSON Schema. Native schemas are compiled and checked for definition errors before validation.

Native FieldSchema:

go run ./cmd/yamlvalidator \
  -schema /tmp/schema.yaml \
  -schema-format field \
  -file ./path/to/config.yaml \
  -strict-keys

Standard JSON Schema, including relative file $ref resolution from the schema file location:

go run ./cmd/yamlvalidator \
  -schema ./schemas/easyp-config-v1.schema.json \
  -schema-format jsonschema \
  -file ./easyp.yaml \
  -assert-format \
  -regexp-timeout 500ms

JSON Schema CLI options: -json-schema-draft, -assert-format, -assert-content, -assert-vocabs, and -regexp-timeout. Validation safety limits are exposed as -max-bytes, -max-documents, -max-depth, and -max-diagnostics. Existing options include -stop-on-first, -yaml11-bools, -sort, plus native-schema-only -strict-keys and -strict-types.

Error Handling

Error Levels
  • LevelError - Critical validation failures
  • LevelWarning - Non-critical issues (deprecated fields, unknown keys in permissive mode)
Error Formatting
result := validator.ValidateBytes(yaml)

// Get all errors
for _, err := range result.Collector.Errors() {
    fmt.Println(err)
}

// Format with source context
fmt.Println(result.FormatAll(true)) // true = sort by position
Example Output
[ERROR] line 2:13: invalid value "v3" (expected one of [v1 v1beta1 apps/v1], got v3) (path: apiVersion)
     1 |
>    2 | apiVersion: v3
       |             ^
     3 | kind: Deployment

[ERROR] line 5:9: must be lowercase DNS-compatible name (got MyApp) (path: metadata.name)
     4 | metadata:
>    5 |   name: MyApp
       |         ^
     6 |   namespace: production

Multi-Document Support

The validator automatically handles multi-document YAML (separated by ---):

name: first
---
name: second
---
name: third

Errors in subsequent documents are prefixed with doc[N].:

[ERROR] line 5:1: required field "name" is missing (path: doc[2].name)

Custom Validators

Value Validator
type MyValidator struct{}

func (v MyValidator) Validate(node *yaml.Node, path string, ctx *ValidationContext) {
    if node.Value != "expected" {
        ctx.AddError(ValidationError{
            Level:   LevelError,
            Path:    path,
            Line:    node.Line,
            Column:  node.Column,
            Message: "value is not expected",
            Got:     node.Value,
        })
    }
}
Key Validator
type MyKeyValidator struct{}

func (v MyKeyValidator) ValidateKey(key string, keyNode *yaml.Node, path string, ctx *ValidationContext) {
    if strings.HasPrefix(key, "_") {
        ctx.AddError(ValidationError{
            Level:   LevelWarning,
            Path:    path,
            Line:    keyNode.Line,
            Column:  keyNode.Column,
            Message: "keys starting with underscore are reserved",
            Got:     key,
        })
    }
}

Best Practices

1. Use AdditionalProperties for arbitrary keys
// Allow any string values for unknown keys
labels: {
    Type:                 TypeMap,
    AdditionalProperties: &FieldSchema{Type: TypeString},
}
2. Combine with key validators
labels: {
    Type:                 TypeMap,
    AdditionalProperties: &FieldSchema{Type: TypeString},
    KeyValidators: []KeyValidator{
        RegexKeyValidator{Pattern: regexp.MustCompile(`^[a-z][a-z0-9._-]*$`)},
    },
}
3. Use Nullable for optional fields that can be explicitly null
timeout: {
    Type:     TypeInt,
    Nullable: true, // Allows: timeout: null
}
4. Use helper functions for pointers
MinItems: Ptr[int](1)
Max:      Ptr[float64](100)

API Reference

Validator
// Preferred for native schemas assembled dynamically
v, err := CompileFieldSchema(schema)

// Backwards-compatible constructor for an already trusted schema
v := NewValidator(schema)

// Validate bytes
result := v.ValidateBytes(yamlData)

// Validate with options
result := v.ValidateWithOptions(yamlData, ValidationContext{...})
ValidationResult
result.HasErrors()              // bool
result.Collector.Errors()       // []ValidationError
result.Collector.Warnings()     // []ValidationError
result.Collector.All()          // []ValidationError in collection order
result.SortByPosition()         // Sort by line/column
result.FormatAll(sortByPos)     // Format with source context
result.Truncated                // true if MaxDiagnostics stopped validation
ValidationError
type ValidationError struct {
    Level      ErrorLevel
    Code       string // Machine-readable code, e.g. "required" or "minimum"
    SchemaPath string // Originating JSON Schema location when available
    Path       string // e.g., "spec.containers[0].image"
    Line       int    // 1-based (0 if unknown)
    Column     int    // 1-based (0 if unknown)
    Message    string
    Got        string // Actual value/type
    Expected   string // Expected value/type
}

License

Apache License 2.0

Documentation

Overview

Package yamlvalidator provides a flexible YAML validation library with support for type checking, custom validators, conditional logic, and detailed error reporting with source context.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FormatErrorWithSource

func FormatErrorWithSource(err ValidationError, lines []string) string

FormatErrorWithSource formats an error with source context. Correctly handles tabs and Unicode.

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to the value. Useful for setting Min/Max fields.

func RenderLineWithCaret

func RenderLineWithCaret(line string, byteCol int) (string, int, int)

RenderLineWithCaret is an exported wrapper useful for external tests and tools.

func ValidateFieldSchema added in v0.3.0

func ValidateFieldSchema(schema *FieldSchema) error

ValidateFieldSchema checks FieldSchema invariants, including nested schemas, invalid constraints, recursive schema graphs, and validator definitions.

Types

type ConditionalRule

type ConditionalRule struct {
	// ConditionField is the field to check.
	ConditionField string
	// ConditionValue is the expected value (scalar comparison).
	ConditionValue string
	// ThenRequired lists fields that become required when condition is met.
	ThenRequired []string
	// ThenForbidden lists fields that are forbidden when condition is met.
	ThenForbidden []string
}

ConditionalRule defines conditional validation logic. When ConditionField equals ConditionValue, additional requirements apply.

type DefinitionValidator added in v0.3.0

type DefinitionValidator interface {
	ValidateDefinition() error
}

DefinitionValidator may be implemented by value/key validators that can validate their own configuration during FieldSchema compilation.

type ErrorCollector

type ErrorCollector struct {
	// contains filtered or unexported fields
}

ErrorCollector accumulates validation errors and warnings.

func NewErrorCollector

func NewErrorCollector() *ErrorCollector

NewErrorCollector creates a new empty ErrorCollector.

func (*ErrorCollector) Add

func (c *ErrorCollector) Add(err ValidationError)

Add adds a validation error to the collector.

func (*ErrorCollector) All

func (c *ErrorCollector) All() []ValidationError

All returns all diagnostics in insertion order.

func (*ErrorCollector) Errors

func (c *ErrorCollector) Errors() []ValidationError

Errors returns all errors.

func (*ErrorCollector) HasErrors

func (c *ErrorCollector) HasErrors() bool

HasErrors returns true if there are any errors (not warnings).

func (*ErrorCollector) Warnings

func (c *ErrorCollector) Warnings() []ValidationError

Warnings returns all warnings.

type ErrorLevel

type ErrorLevel int

ErrorLevel defines the severity of a validation error.

const (
	// LevelWarning indicates a non-critical issue (e.g., deprecated field, unknown key in permissive mode).
	LevelWarning ErrorLevel = iota
	// LevelError indicates a critical validation failure.
	LevelError
)

func (ErrorLevel) String

func (l ErrorLevel) String() string

type FieldSchema

type FieldSchema struct {
	// Type is the expected node type.
	Type NodeType

	// AllowedTypes accepts any of the listed node types. When non-empty it
	// takes precedence over Type and is useful for schema unions.
	AllowedTypes []NodeType

	// Required indicates the field must be present.
	Required bool

	// Nullable allows null values even when Type is not TypeNull.
	Nullable bool

	// Deprecated contains a deprecation message (empty = not deprecated).
	// Use "true" for a generic message.
	Deprecated string

	// Description is a human-readable field description.
	Description string

	// Default is the default value. If set and field is missing, a warning is emitted.
	Default interface{}

	// AllowedKeys defines known keys and their schemas.
	// If nil, ALL keys are considered unknown.
	// This does NOT mean "don't check" - it means "no known keys".
	//
	// For "any keys allowed, no validation":
	//   AllowedKeys: nil,
	//   AdditionalProperties: &FieldSchema{Type: TypeAny},
	//
	// For "don't touch this map at all":
	//   AllowedKeys: nil,
	//   AdditionalProperties: nil,
	//   UnknownKeyPolicy: UnknownKeyIgnore,
	AllowedKeys map[string]*FieldSchema

	// AdditionalProperties is the schema for keys not in AllowedKeys.
	// If not nil: unknown keys are allowed and validated against this schema.
	// If nil: unknown keys are handled by UnknownKeyPolicy.
	AdditionalProperties *FieldSchema

	// UnknownKeyPolicy determines handling of keys not in AllowedKeys
	// when AdditionalProperties is nil.
	UnknownKeyPolicy UnknownKeyPolicy

	// KeyValidators validate key names (applied to ALL keys).
	KeyValidators []KeyValidator

	// ItemSchema is the schema for sequence items.
	ItemSchema *FieldSchema

	// MinItems is the minimum number of items (nil = no limit).
	MinItems *int

	// MaxItems is the maximum number of items (nil = no limit).
	MaxItems *int

	// Validators are custom value validators.
	Validators []ValueValidator

	// AnyOf requires at least one field group to be fully present.
	// Example: [][]string{{"configFile"}, {"host", "port"}}
	// Means: either configFile, OR both host AND port.
	AnyOf [][]string

	// ExactlyOneOf requires exactly one field from the list.
	// Example: []string{"inline", "file", "url"}
	// Means: exactly one of inline/file/url must be present.
	ExactlyOneOf []string

	// MutuallyExclusive allows at most one field from the list (zero is OK).
	// Example: []string{"debug", "quiet"}
	// Means: debug and quiet cannot both be present.
	MutuallyExclusive []string

	// Conditions define conditional validation rules.
	Conditions []ConditionalRule

	// OneOfSchemas requires exactly one child schema to validate successfully.
	OneOfSchemas []*FieldSchema

	// AnyOfSchemas requires at least one child schema to validate successfully.
	AnyOfSchemas []*FieldSchema

	// OneOfRequired requires exactly one field group to be fully present.
	OneOfRequired [][]string

	// ForbiddenTogether rejects groups whose fields are all present together.
	ForbiddenTogether [][]string

	// DependentRequired requires additional fields when a trigger field is present.
	DependentRequired map[string][]string
}

FieldSchema defines the validation rules for a field.

func CompileJSONSchema added in v0.3.0

func CompileJSONSchema(data []byte) (*FieldSchema, error)

CompileJSONSchema compiles a JSON Schema using draft 2020-12 as the default dialect. Schemas declaring $schema are compiled using their declared dialect.

func CompileJSONSchemaWithOptions added in v0.3.0

func CompileJSONSchemaWithOptions(data []byte, opts JSONSchemaCompileOptions) (*FieldSchema, error)

CompileJSONSchemaWithOptions compiles a standards-compliant JSON Schema and returns a FieldSchema adapter that validates YAML through the JSON Schema engine while preserving YAML source positions in diagnostics.

type JSONSchemaCompileOptions added in v0.3.0

type JSONSchemaCompileOptions struct {
	// SchemaURL is the retrieval URL of the root schema. It is used as the base
	// URI for relative references when the schema does not establish another base
	// with $id. The default is an in-memory HTTPS URL.
	SchemaURL string

	// DefaultDraft is used only when the schema does not contain $schema.
	// The default is draft 2020-12.
	DefaultDraft JSONSchemaDraft

	// AssertFormat forces format to be an assertion even in dialects where it is
	// annotation-only by default.
	AssertFormat bool

	// AssertContent enables contentEncoding/contentMediaType/contentSchema assertions.
	AssertContent bool

	// AssertVocabs requires vocabularies declared by a metaschema to be known.
	AssertVocabs bool

	// RegexpTimeout bounds one ECMAScript regexp match. Zero preserves the
	// regexp engine's unlimited default. Use a positive duration for untrusted schemas.
	RegexpTimeout time.Duration

	// Formats registers first-class functional custom formats.
	Formats []JSONSchemaFormat

	// Keywords registers functional custom keywords in an internal vocabulary.
	// They are activated for this compilation automatically.
	Keywords []JSONSchemaKeyword

	// Vocabularies registers named functional custom vocabularies. They are
	// activated for this compilation automatically.
	Vocabularies []JSONSchemaVocabulary

	// Resources preloads external resources addressed by their retrieval URLs.
	// This is the preferred way to compile a closed schema graph without I/O.
	Resources map[string][]byte

	// LoadURL loads unresolved external references. If nil, the underlying engine
	// retains its default file:// loader; HTTP(S) loading is never enabled implicitly.
	LoadURL JSONSchemaLoadFunc

	// ConfigureCompiler is an advanced escape hatch exposing the underlying
	// compiler before resources are added. It can register custom vocabularies,
	// formats, content encodings/media types, or override other engine settings.
	ConfigureCompiler func(*jsonschema.Compiler) error

	// AdditionalPropertiesFalsePolicy optionally downgrades direct
	// additionalProperties:false diagnostics. This is a presentation policy and
	// intentionally does not rewrite JSON Schema combinator semantics.
	AdditionalPropertiesFalsePolicy *UnknownKeyPolicy
}

JSONSchemaCompileOptions controls JSON Schema compilation and validation.

type JSONSchemaDraft added in v0.3.0

type JSONSchemaDraft string

JSONSchemaDraft selects the default JSON Schema dialect used when a schema does not declare $schema. An explicit $schema in the document takes precedence.

const (
	JSONSchemaDraft4    JSONSchemaDraft = "draft-04"
	JSONSchemaDraft6    JSONSchemaDraft = "draft-06"
	JSONSchemaDraft7    JSONSchemaDraft = "draft-07"
	JSONSchemaDraft2019 JSONSchemaDraft = "2019-09"
	JSONSchemaDraft2020 JSONSchemaDraft = "2020-12"
)

type JSONSchemaFormat added in v0.3.0

type JSONSchemaFormat struct {
	Name     string
	Validate func(value any) error
}

JSONSchemaFormat registers a custom JSON Schema format without exposing the underlying JSON Schema engine API.

type JSONSchemaKeyword added in v0.3.0

type JSONSchemaKeyword struct {
	Name     string
	Validate JSONSchemaKeywordFunc
	Compile  JSONSchemaKeywordCompileFunc
}

JSONSchemaKeyword defines one custom JSON Schema keyword. Set exactly one of Validate or Compile.

type JSONSchemaKeywordCompileFunc added in v0.3.0

type JSONSchemaKeywordCompileFunc func(
	keywordValue any,
) (JSONSchemaKeywordValidateFunc, error)

JSONSchemaKeywordCompileFunc compiles a keyword value from the schema into a runtime validation function. It is useful for parsing/validating keyword configuration once instead of on every validation call.

type JSONSchemaKeywordFunc added in v0.3.0

type JSONSchemaKeywordFunc func(
	keywordValue any,
	instance any,
	ctx *JSONSchemaKeywordValidationContext,
)

JSONSchemaKeywordFunc is the simple custom-keyword form. The schema keyword value and current JSON instance value are supplied on each validation call.

type JSONSchemaKeywordIssue added in v0.3.0

type JSONSchemaKeywordIssue struct {
	Path    []string
	Message string
}

JSONSchemaKeywordIssue is a diagnostic produced by a custom JSON Schema keyword. Path is relative to the instance value to which the keyword applies.

type JSONSchemaKeywordValidateFunc added in v0.3.0

type JSONSchemaKeywordValidateFunc func(
	instance any,
	ctx *JSONSchemaKeywordValidationContext,
)

JSONSchemaKeywordValidateFunc validates one JSON instance value.

type JSONSchemaKeywordValidationContext added in v0.3.0

type JSONSchemaKeywordValidationContext struct {
	// contains filtered or unexported fields
}

JSONSchemaKeywordValidationContext collects custom keyword diagnostics and evaluation annotations during one keyword validation call.

func (*JSONSchemaKeywordValidationContext) AddError added in v0.3.0

func (ctx *JSONSchemaKeywordValidationContext) AddError(message string)

AddError reports an error for the current instance value.

func (*JSONSchemaKeywordValidationContext) AddErrorAt added in v0.3.0

func (ctx *JSONSchemaKeywordValidationContext) AddErrorAt(path []string, message string)

AddErrorAt reports an error at a path relative to the current instance value.

func (*JSONSchemaKeywordValidationContext) MarkItemEvaluated added in v0.3.0

func (ctx *JSONSchemaKeywordValidationContext) MarkItemEvaluated(index int)

MarkItemEvaluated marks an array item as evaluated for unevaluatedItems semantics.

func (*JSONSchemaKeywordValidationContext) MarkPropertyEvaluated added in v0.3.0

func (ctx *JSONSchemaKeywordValidationContext) MarkPropertyEvaluated(name string)

MarkPropertyEvaluated marks an object property as evaluated for unevaluatedProperties semantics.

type JSONSchemaLoadFunc added in v0.3.0

type JSONSchemaLoadFunc func(url string) ([]byte, error)

JSONSchemaLoadFunc loads an external JSON Schema resource by absolute URL. The returned bytes must contain a JSON document.

type JSONSchemaVocabulary added in v0.3.0

type JSONSchemaVocabulary struct {
	URL      string
	Keywords []JSONSchemaKeyword
}

JSONSchemaVocabulary groups custom keywords under a vocabulary URL. Vocabularies registered through JSONSchemaCompileOptions are activated for that compilation. For declaration-only/advanced vocabulary semantics use ConfigureCompiler.

type KeyValidator

type KeyValidator interface {
	ValidateKey(key string, keyNode *yaml.Node, path string, ctx *ValidationContext)
}

KeyValidator validates key names in mappings.

type NodeType

type NodeType int

NodeType represents the expected YAML node type.

const (
	// TypeAny accepts any type.
	TypeAny NodeType = iota
	// TypeNull represents null/nil values.
	TypeNull
	// TypeString represents string values.
	TypeString
	// TypeInt represents integer values.
	TypeInt
	// TypeFloat represents floating-point values (also accepts int).
	TypeFloat
	// TypeBool represents boolean values.
	TypeBool
	// TypeMap represents mapping nodes.
	TypeMap
	// TypeSequence represents sequence/array nodes.
	TypeSequence
)

func (NodeType) String

func (t NodeType) String() string

type UnknownKeyPolicy

type UnknownKeyPolicy int

UnknownKeyPolicy determines how unknown keys in maps are handled.

const (
	// UnknownKeyInherit uses ctx.StrictKeys to decide:
	//   StrictKeys=true  -> error
	//   StrictKeys=false -> warning
	UnknownKeyInherit UnknownKeyPolicy = iota

	// UnknownKeyError treats unknown keys as errors.
	UnknownKeyError

	// UnknownKeyWarn treats unknown keys as warnings.
	UnknownKeyWarn

	// UnknownKeyIgnore silently ignores unknown keys.
	UnknownKeyIgnore
)

type ValidationContext

type ValidationContext struct {
	// StrictKeys determines the default behavior for unknown keys
	// when UnknownKeyPolicy is UnknownKeyInherit:
	//   true  -> unknown keys are errors
	//   false -> unknown keys are warnings
	StrictKeys bool

	// StopOnFirst stops validation after the first error.
	StopOnFirst bool

	// StrictTypes uses only YAML tags for type inference.
	// When false, values are parsed to infer types (e.g., "123" -> int).
	StrictTypes bool

	// YAML11Booleans enables YAML 1.1 boolean literals (yes/no/on/off).
	// By default, only YAML 1.2 booleans (true/false) are recognized.
	YAML11Booleans bool

	// MaxBytes rejects inputs larger than this many bytes. Zero means unlimited.
	MaxBytes int

	// MaxDocuments limits the number of YAML documents in a stream. Zero means unlimited.
	MaxDocuments int

	// MaxDepth limits YAML container/schema traversal depth. The root value has depth 1.
	// Zero means unlimited.
	MaxDepth int

	// MaxDiagnostics stops validation after this many errors/warnings. Zero means unlimited.
	MaxDiagnostics int

	// SourceLines contains the original YAML lines for error formatting.
	SourceLines []string
	// contains filtered or unexported fields
}

ValidationContext holds configuration and state for a validation run.

func NewValidationContext

func NewValidationContext() *ValidationContext

NewValidationContext creates a new ValidationContext with default settings.

func (*ValidationContext) AddError

func (ctx *ValidationContext) AddError(err ValidationError)

AddError adds an error to the context's collector.

func (*ValidationContext) Collector

func (ctx *ValidationContext) Collector() *ErrorCollector

Collector returns the error collector.

func (*ValidationContext) IsStopped

func (ctx *ValidationContext) IsStopped() bool

IsStopped returns true if validation has been stopped.

type ValidationError

type ValidationError struct {
	Level      ErrorLevel
	Code       string // Stable machine-readable diagnostic code when available.
	SchemaPath string // Schema location that produced the diagnostic, when available.
	Path       string // Path to the problematic node, e.g., "spec.containers[0].image"
	Line       int    // 1-based line number (0 if unknown)
	Column     int    // 1-based column number (0 if unknown)
	Message    string
	Got        string // Actual value/type description
	Expected   string // Expected value/type description
}

ValidationError represents a single validation issue.

func (ValidationError) Error

func (e ValidationError) Error() string

type ValidationResult

type ValidationResult struct {
	// Collector contains all errors and warnings.
	Collector *ErrorCollector
	// SourceLines contains the original YAML lines.
	SourceLines []string
	// Truncated reports that validation stopped because MaxDiagnostics was reached.
	Truncated bool
}

ValidationResult contains the validation outcome and context for formatting.

func (*ValidationResult) FormatAll

func (r *ValidationResult) FormatAll(sortByPos bool) string

FormatAll formats all errors with source context.

func (*ValidationResult) HasErrors

func (r *ValidationResult) HasErrors() bool

HasErrors returns true if there are any errors.

func (*ValidationResult) SortByPosition

func (r *ValidationResult) SortByPosition()

SortByPosition sorts errors by position in the file.

type Validator

type Validator struct {
	// contains filtered or unexported fields
}

Validator performs YAML validation against a schema.

func CompileFieldSchema added in v0.3.0

func CompileFieldSchema(schema *FieldSchema) (*Validator, error)

CompileFieldSchema validates a native FieldSchema before constructing a Validator. New code should prefer this over NewValidator when schemas are assembled dynamically or loaded from configuration.

func NewValidator

func NewValidator(schema *FieldSchema) *Validator

NewValidator creates a new Validator with the given schema.

func (*Validator) InferTypeForPublic

func (v *Validator) InferTypeForPublic(node *yaml.Node, ctx *ValidationContext) NodeType

InferTypeForPublic exposes internal type inference for external validators.

func (*Validator) ValidateBytes

func (v *Validator) ValidateBytes(data []byte) *ValidationResult

ValidateBytes validates YAML data and returns the result. Supports multi-document YAML (separated by ---).

func (*Validator) ValidateWithOptions

func (v *Validator) ValidateWithOptions(data []byte, opts ValidationContext) *ValidationResult

ValidateWithOptions validates YAML data with custom options.

type ValueValidator

type ValueValidator interface {
	Validate(node *yaml.Node, path string, ctx *ValidationContext)
}

ValueValidator validates a node's value.

Directories

Path Synopsis
cmd
yamlvalidator command
examples
basic command
Example demonstrates how to use the yamlvalidator package to validate Kubernetes-like manifests with comprehensive schema definitions.
Example demonstrates how to use the yamlvalidator package to validate Kubernetes-like manifests with comprehensive schema definitions.
easyp command
internal
thirdparty/xnet/idna
Package idna implements IDNA2008 using the compatibility processing defined by UTS (Unicode Technical Standard) #46, which defines a standard to deal with the transition from IDNA2003.
Package idna implements IDNA2008 using the compatibility processing defined by UTS (Unicode Technical Standard) #46, which defines a standard to deal with the transition from IDNA2003.
thirdparty/xtext/secure/bidirule
Package bidirule implements the Bidi Rule defined by RFC 5893.
Package bidirule implements the Bidi Rule defined by RFC 5893.
thirdparty/xtext/transform
Package transform provides reader and writer wrappers that transform the bytes passing through as well as various transformations.
Package transform provides reader and writer wrappers that transform the bytes passing through as well as various transformations.
thirdparty/xtext/unicode/bidi
Package bidi contains functionality for bidirectional text support.
Package bidi contains functionality for bidirectional text support.
thirdparty/xtext/unicode/norm
Package norm contains types and functions for normalizing Unicode strings.
Package norm contains types and functions for normalizing Unicode strings.
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL