kdl

package module
v0.0.0-...-8b70533 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2026 License: MIT Imports: 8 Imported by: 8

README

KDLv1 Library for Go

kdl-go is a Go library for version 1 of the KDL Document Language. It supports encoding and decoding KDL documents, marshaling and unmarshaling them into Go structs.

Features

  • supports all KDLv1 language features and passes all of the official KDLv1 test cases as of time of writing
  • designed with performance and usability in mind
  • familiar API and tag syntax, similar to encoding/json
  • supports marshaling/unmarshaling into Go structures with support for encoding.Text(Un)Marshaler and its own custom marshal/unmarshal interfaces
  • support for encoding/json/v2-style format options for time.Time, time.Duration, []byte, and float32/64
  • contextual errors, including the line and column of each error and a sample line displaying the error location

Import

import "github.com/sblinch/kdl-go"

Decoding

Parse() decodes KDL to a *document.Document:

data := `
    name "Bob"
    age 76
    active true
`

if doc, err := kdl.Parse(strings.NewReader(data)); err == nil {
    // print the top-level nodes
    for _, node := range doc.Nodes {
        fmt.Println(node.Name.String())
    }
}
// output
name
age
active

Encoding

Generate() generates KDL from a *document.Document:

data := `
    name "Bob"
    age 76
    active true
`

if doc, err := Parse(strings.NewReader(data)); err == nil {
    // output the KDL representation of doc to stdout
    if err := Generate(doc, os.Stdout); err != nil {
        panic(err)
    }
}
// output:
name "Bob"
age 76
active true

Unmarshaling

via Unmarshal

Unmarshal() unmarshals KDL to a Go map or struct. The kdl tag can be used to map KDL node names to struct fields or otherwise change unmarshaling behavior:

type Person struct {
    Name        string      `kdl:"name"`
    Age         int         `kdl:"age"`
    Active      bool        `kdl:"active"`
}

data := `
    name "Bob"
    age 76
    active true
`

var person Person
if err := kdl.Unmarshal(data, &person); err == nil {
    fmt.Printf("%+v\n",person)
}
// output
Person{
    Name: "Bob",
    Age: 76,
    Active: true
}

kdl-go's unmarshaler is described in detail in Unmarshaling in kdl-go.

via Decoder

Use kdl.NewDecoder() to create a new KDL decoder whose options can be customized to your needs:

type Person struct {
    Name        string      `kdl:"name"`
    Age         int         `kdl:"age"`
    Active      bool        `kdl:"active"`
}

data := `
    name "Bob"
    age 76
    active true
    geriatric true
`

var person Person
dec := kdl.NewDecoder(strings.NewReader(data))

// ignore the unhandled "geriatric" node 
dec.Options.AllowUnhandledNodes = true

if err := dec.Decode(&person); err == nil {
    fmt.Printf("%+v\n", person)
}
// output
Person{
    Name: "Bob",
    Age: 76, 
    Active: true
}

Marshaling

via Marshal

Marshal() marshals a Go map or struct into KDL. The kdl tag can be used to map struct fields to KDL node names or otherwise change marshaling behavior:

type Person struct {
    Name   string `kdl:"name"`
    Age    int    `kdl:"age"`
    Active bool   `kdl:"active"`
}

person := Person{
    Name:   "Bob",
    Age:    32,
    Active: true,
}

if data, err := kdl.Marshal(person); err == nil {
    fmt.Println(string(data))
}
// output:
name "Bob"
age 32
active true

kdl-go's marshaler is described in detail in Marshaling in kdl-go.

via Encoder

Use kdl.NewEncoder() to create a new KDL encoder whose options can be customized to your needs:

type Person struct {
    Name   string `kdl:"name"`
    Age    int    `kdl:"age"`
    Active bool   `kdl:"active"`
}

person := Person{
    Name:   "Bob Jones",
    Age:    32,
    Active: true,
}

enc := kdl.NewEncoder(os.Stdout)
if err := enc.Encode(person); err != nil {
	panic(err)
}
//output
name "Bob Jones"
age 32
active true

nginx-style Syntax Mode

kdl-go can also parse nginx-style configuration files using its relaxed.NGINXSyntax mode:

data := `
    # web root
    location / {
        root /var/www/html;
    }

    # a missing location
    location /missing {
        return 404;
    }
`

type Location struct {
    Root   string `kdl:"root,omitempty,child"`
    Return int    `kdl:"return,omitempty,child"`
}
type NginxServer struct {
    Locations map[string]Location `kdl:"location,multiple"`
}

var ngx NginxServer
dec := kdl.NewDecoder(strings.NewReader(data))
dec.Options.RelaxedNonCompliant |= relaxed.NGINXSyntax

if err := dec.Decode(&ngx); err == nil {
    fmt.Printf("%#v\n", ngx)
}
// output:
NginxServer{
    Locations: {
        "/": { Root:"/var/www/html", Return:0 }, 
        "/missing": { Root:"", Return:404 }
    }
}

See the unmarshaling docs for further information.

Verifying Spec Compliance

To download and test against all Full Document Test Cases from the kdl.org repository, run:

git clone https://github.com/sblinch/kdl-go
cd kdl-go
git clone --branch release/v1 https://github.com/kdl-org/kdl kdl-org
cd internal/parser
go test -v -run TestKDLOrgTestCases -tags kdldeterministic

As of October 2023, kdl-go passes all of the available test cases.

Development Status

kdl-go is actively maintained and is has been used as a configuration unmarshaler in a number of production applications for several years now. It is considered stable at this time.

Issue reports and pull requests are welcome.

On KDLv2

kdl-go implements the KDLv1 specification only.

The KDLv2 specification introduces some changes that this maintainer is not comfortable implementing as explained in issue #6. Similar concerns have been raised by other users as well (eg: here and here). As such, support for KDLv2 is not planned at this time.

License

kdl-go is released under the MIT license. See LICENSE for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultGenerateOptions = generator.DefaultOptions
View Source
var DefaultParseOptions = parser.ParseContextOptions{}

Functions

func AddCustomMarshaler

func AddCustomMarshaler[T any](marshal func(v reflect.Value, node *document.Node) error)

func AddCustomUnmarshaler

func AddCustomUnmarshaler[T any](unmarshal func(node *document.Node, v reflect.Value) error)

func AddCustomValueMarshaler

func AddCustomValueMarshaler[T any](marshal func(v reflect.Value, value *document.Value, format string) error)

func AddCustomValueUnmarshaler

func AddCustomValueUnmarshaler[T any](unmarshal func(value *document.Value, v reflect.Value, format string) error)

func Generate

func Generate(doc *document.Document, w io.Writer) error

Generate writes to w a well-formatted KDL document generated from doc, or a non-nil error on failure

func GenerateWithOptions

func GenerateWithOptions(doc *document.Document, w io.Writer, opts GenerateOptions) error

GenerateWithOptions writes to w a well-formatted KDL document generated from doc, or a non-nil error on failure

func Marshal

func Marshal(v interface{}) ([]byte, error)

Marshal returns the KDL representation of v, or a non-nil error on failure

func MarshalDocument

func MarshalDocument(v interface{}, doc *document.Document) error

func MarshalDocumentWithOptions

func MarshalDocumentWithOptions(v interface{}, doc *document.Document, opts marshaler.MarshalOptions) error

func MarshalNode

func MarshalNode(v interface{}) (*document.Node, error)

func MarshalNodeWithOptions

func MarshalNodeWithOptions(v interface{}, opts marshaler.MarshalOptions) (*document.Node, error)

func MarshalWithOptions

func MarshalWithOptions(v interface{}, opts MarshalOptions) ([]byte, error)

MarshalWithOptions returns the KDL representation of v using the specified Options, or a non-nil error on failure

func Parse

func Parse(r io.Reader) (*document.Document, error)

Parse parses a KDL document from r and returns the parsed Document, or a non-nil error on failure

func ParseWithOptions

func ParseWithOptions(r io.Reader, opts ParseOptions) (*document.Document, error)

func Unmarshal

func Unmarshal(data []byte, v interface{}) error

Unmarshal unmarshals KDL from data into v; v must contain a pointer type. Returns a non-nil error on failure.

func UnmarshalDocument

func UnmarshalDocument(doc *document.Document, v interface{}) error

func UnmarshalDocumentWithOptions

func UnmarshalDocumentWithOptions(doc *document.Document, v interface{}, opts UnmarshalOptions) error

func UnmarshalNode

func UnmarshalNode(node *document.Node, v interface{}) error

func UnmarshalNodeWithOptions

func UnmarshalNodeWithOptions(node *document.Node, v interface{}, opts UnmarshalOptions) error

func UnmarshalWithOptions

func UnmarshalWithOptions(data []byte, v interface{}, opts UnmarshalOptions) error

UnmarshalWithOptions unmarshals KDL from data into v with the specified options; v must contain a pointer type. Returns a non-nil error on failure.

Types

type Decoder

type Decoder struct {
	Options marshaler.UnmarshalOptions
	// contains filtered or unexported fields
}

Decoder implements a decoder for KDL

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a Decoder that reads from r

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{}) error

Decode decodes KDL from the Decoder's reader into v; v must contain a pointer type. Returns a non-nil error on failure.

type Encoder

type Encoder struct {
	Options MarshalOptions
	// contains filtered or unexported fields
}

Encoder implements an encoder for KDL

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder creates a new Encoder that writes to w

func (*Encoder) Encode

func (e *Encoder) Encode(v interface{}) error

Encode encodes v into KDL and writes it to the Encoder's writer, and returns a non-nil error on failure

type GenerateOptions

type GenerateOptions = generator.Options

type GeneratorOptions

type GeneratorOptions = generator.Options

type MarshalOptions

type MarshalOptions struct {
	MarshalerOptions
	GeneratorOptions
}

type Marshaler

type Marshaler interface {
	MarshalKDL(node *document.Node) error
}

Marshaler provides an interface for custom marshaling of a Go type into a Node

type MarshalerOptions

type MarshalerOptions = marshaler.MarshalOptions

type ParseOptions

type ParseOptions = parser.ParseContextOptions

type UnmarshalOptions

type UnmarshalOptions = marshaler.UnmarshalOptions

type Unmarshaler

type Unmarshaler interface {
	UnmarshalKDL(node *document.Node) error
}

Unmarshaler provides an interface for custom unmarshaling of a node into a Go type

type ValueMarshaler

type ValueMarshaler interface {
	MarshalKDLValue(value *document.Value) error
}

ValueMarshaler provides an interface for custom marshaling of a Go type into a Value (such as a node argument or property)

type ValueUnmarshaler

type ValueUnmarshaler interface {
	UnmarshalKDLValue(value *document.Value) error
}

ValueUnmarshaler provides an interface for custom unmarshaling of a Value (such as a node argument or property) into a Go type

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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