Skip to content

API overview

The package is one public surface: a File that holds immutable revisions, Snapshot, Document and Node views into a revision, typed reads, and one Transaction shape for edits. Every method's signature and doc comment is on pkg.go.dev; this page is the map, and says what each piece is for and how the pieces relate.

Parsing

f, err := yamldoc.Parse(src, yamldoc.Options{})

Options selects the language (Version, zero to let each document negotiate its own from its directives), the schema profiles per document (Profiles, nil for each document's default), and the resource limits. Every limit left at zero takes the value DefaultLimits returns, which is sized for configuration files; an explicit limit always wins.

Parse is strict. Bytes that are not YAML under the selected language return an error and no File: ErrSyntax, ErrUnsupportedVersion for a %YAML directive naming a version the engine does not implement, ErrVersionConflict when a directive disagrees with Options.Version, ErrEncoding for bytes that are not valid in their encoding, or ErrSyntaxLimit. A document that is YAML but not meaningful under its schema parses; see Validation.

Every other directive is accepted. Document.Directives reports what a document declared, %YAML, %TAG and reserved names alike, each with its parameters and location, so a reader that allows none can refuse them itself:

directives, err := doc.Directives()
if err != nil {
    return err
}

if len(directives) > 0 {
    first := directives[0]
    return fmt.Errorf("line %d: %%%s directives are not allowed", first.Location.Start.Line, first.Name)
}

Revisions and views

A File publishes immutable revisions. f.Snapshot() is the current one, and a Snapshot keeps describing that revision however many edits land afterwards, so a reader never sees a half-applied change and a handle never goes stale on its own.

View Reached by What it is
Snapshot File.Snapshot, Transaction.Snapshot One revision: its Bytes, its Documents, its stream Comments, and Validate
Document Snapshot.Document(i), Snapshot.Documents One document: Root, Index, Version, the Directives it declared, document-level Comments, and the dotted-path helpers
Node Document.Root, Node.Get, Entries, Items One syntax occurrence: a scalar, mapping, sequence or alias
Entry Node.Entries A mapping's key and value nodes, with the entry's Comments
Mapping, Sequence Node.Mapping, Node.Sequence, Node.Value A collection view, with typed Lookup and Items

A working snapshot taken inside Edit expires when the callback returns; a committed snapshot lives as long as you hold it.

Addressing

Node.Get(steps ...Step) walks from a node. A Step is one of:

Step Addresses
StringStep("key") The entry whose key is the string key, exactly as spelt: a key containing a dot is one step
IndexStep(i) The ith item of a sequence
KeyStep(key) The entry whose key equals a typed Key: IntKey(8080) matches 8080, 0x1f90 and 0o17620 alike

Document.Get("a.b.c") is sugar for Root().Get(StringStep("a"), StringStep("b"), StringStep("c")); PathSteps does the split on its own. Paths and steps has the rules.

Reading

Every read is typed and returns an error rather than a zero value when the node is not what was asked for.

Method Returns Fails with
String, Bool, Int64, Uint64, Float64, Float32, Time, Binary The value, if the node resolves to that type under the document's schema ErrKind for another type, ErrRange or ErrPrecision when the value does not fit
BigInt, Rat, Number The exact value, for integers beyond int64 and decimals beyond float64 ErrKind
Value The native Go value: scalars as above, nil for null, Mapping or Sequence for collections ErrSemantic when the subtree is invalid
Project(expandAliases) A recursive native projection, map[string]any and []any all the way down, with an Origin (location, key location, path, alias hops) for every value The projection limits, alias errors unless expansion is requested, a << key
Raw, LiteralText, Syntax The source bytes, the decoded text, and the kind, style, tag, anchor and location Nothing beyond an expired view
Entries, Items, Comments, ItemComments Literal structure and comment ownership, valid even where semantics are not ErrKind on the wrong kind
CommentOwner, ItemCommentOwner The owner a comment command names as its destination; Snapshot, Document and Entry have CommentOwner too ErrKind on the wrong kind
AliasTarget The anchored node an alias refers to ErrKind on a non-alias
EvaluateMerge(limits) The mapping with << merge keys applied, under a profile that supports them, each inherited entry carrying the MergeHop that supplied it Merge errors; zero limits

Which spellings are which type depends on the document's version: yes is a boolean under 1.1 and a string under 1.2, 0777 is octal under 1.1 and decimal under 1.2. Document.Version says which rules apply. Reading a document works every one of these against one file, provenance and merge keys included.

Editing

err := f.Edit(func(tx *yamldoc.Transaction) error { ... })

The callback is the transaction. Commands stage changes against a private working revision; when the callback returns nil the engine re-parses the result, checks it against an independent statement of every staged edit, and publishes it. Any error, from a command or from the callback, discards the lot. A command's error poisons the transaction even if the callback ignores it.

Command Does
Set(container, key, value) Writes a mapping entry, creating it at the end when absent
ReplaceEntry(container, key, value) Writes an existing entry; absent is ErrNotFound
Insert(container, step, value) Adds a new mapping entry (absent key) or a sequence item before IndexStep(i); an existing key is ErrExists
Replace(target, value) Replaces a selected node, whatever its kind; the way to change a sequence item
Remove(container, step), RemoveIfPresent Removes an entry or item, with or without tolerating absence
CreateDocument(value), CreateDocumentWithProfile Gives an empty stream its first document; a stream with one is ErrDocumentExists
ChangeComments(changes) Moves or copies comments to an entry or item, a block collection's tail, a document marker, the gap between documents, or the stream's header or footer; see Move or copy a comment
ReplaceWithComments(target, value, changes) Replaces a node and moves or copies comments in one command, including into the new value with InReplacement

Every command produces a new working revision and expires every Node from the previous one, so take tx.Snapshot() again before the next command. A handle from another revision is ErrStale; a helper such as Document.Set called inside a callback is ErrActiveTransaction.

Writes accept strings, booleans, all integer and float widths, *big.Int, time.Time, []byte, nil, maps, slices and arrays, and MappingInput for an ordered mapping. Normalize turns one into the Graph the engine writes, and Node.Detach gives back a Graph you can write elsewhere.

Dotted-path helpers

Document.Set(path, value) and Document.Remove(path) each run one Edit containing one command, with Set creating missing mapping ancestors (and a one-item sequence for a missing [0]); a path's [n] is the nth item of a sequence, replaced in place, appended at the sequence's length and ErrNotFound beyond, or the integer key n of a mapping. They are convenience for a single change and offer no atomicity across calls. Document.Get(path) needs no transaction.

Validation

Snapshot.Validate composes the revision's semantics under its profiles and returns a ValidationReport: the diagnostics with locations and related locations, and the checks that could not run because a node they depend on had already failed. It errors when any diagnostic is a genuine failure. Validate a document shows it in use.

Profiles

A Profile is a Base schema, Core, JSON, Strings, Failsafe or the YAML 1.1 Standard11, with Extensions for the standard timestamp and binary types, implicit timestamp recognition and merge-key support. NewProfile refuses combinations outside the nineteen the design froze; DefaultProfile(version) is what a document gets without an override.

Resolvers

Custom application tags such as !secret vault/database can be resolved on request through a ResolverRegistry attached to a ResolverSet. Parsing, reading, validating and emitting never invoke a resolver; a caller asks for a specific tagged node and receives a Resolved envelope carrying the handler's payload. The registry API is documented on pkg.go.dev, and a consumer that does not register anything is not affected by it.

Limits

Every operation is bounded: source bytes, nodes, depth, comments, work per transaction. The types behind Options.Limits are aliased here (SyntaxLimits, ComposeLimits, EditLimits and so on) so a caller can set them without importing internal packages. The zero value means the default, and the defaults are measured against real configuration files. The ones a caller is likeliest to meet:

Limit Default Refuses
Nodes, in every layer 100,000 a mapping of more than about 50,000 entries
Syntax.Bytes 64 MiB a larger source
Syntax.Depth 256 deeper nesting
Edit.Commands 1,000 a longer batch in one transaction
Edit.RevisionBytes 256 MiB a batch whose working revisions hold more

DefaultLimits returns every field.