Custom formats¶
The format driver reads config files of any format with nested objects. The format is set by a function that decodes the content to a map, everything else is the same as in the yaml, json and toml drivers: several files, merging, embedded files, remote documents, environment variables in the content, reloading, documentation.
import "github.com/insei/tinyconf/drivers/format"
driver, err := format.New("hujson", decodeHuJSON, "config.hujson")
The name of the driver is the name of the struct tag with the keys, and the name for GenDoc:
Decoder¶
The decoder returns the content as a map:
- keys of the map are the keys of the config, nested maps with string keys are nested objects;
- slices are lists, other values are scalars: strings, numbers, booleans,
time.Time; - empty content can be decoded to a nil map.
Values are converted to the types of the fields by the same rules as the values of yaml and json, see Supported types.
For example, HuJSON — JSON with comments and trailing commas:
import "github.com/tailscale/hujson"
func decodeHuJSON(data []byte) (map[string]any, error) {
data, err := hujson.Standardize(data)
if err != nil {
return nil, err
}
var doc map[string]any
return doc, json.Unmarshal(data, &doc)
}
Libraries that decode to the structs only, like HCL, need the conversion of their result to the map.
Options¶
| Option | Description |
|---|---|
WithFiles(files...) |
additional files from the OS file system |
WithFS(fsys, files...) |
files from any fs.FS, embed.FS for example |
WithData(name, data) |
in-memory content, the name is used in error messages |
WithSource(source) |
content from a remote storage: consul.Document, etcd.Document |
WithOptional() |
files can be absent |
WithEnvExpansion() |
replaces ${VAR} in the content with environment variables |
WithWatchInterval(interval) |
interval of polling the files for reloading, 5 seconds by default |
WithEncoder(encode) |
encoder of the documents for GenDoc |
The rules of the files are the same as in the yaml driver.
Documentation¶
GenDoc needs the encoder:
type Encoder func(doc map[string]any) ([]byte, error)
driver, err := format.New("hujson", decodeHuJSON, "config.hujson", format.WithEncoder(func(doc map[string]any) ([]byte, error) {
return json.MarshalIndent(doc, "", " ")
}))
The document has the same structure as the result of the decoder, with the current values of the registered configs; values of hidden:"true" fields are empty strings. Without the encoder GenDoc returns an empty string.
Not a file format?¶
If the values are not stored as documents — a database, an API, a secret manager — write a custom driver.