Documentation
¶
Overview ¶
Package flat flattens nested maps into single-depth maps with delimited keys and unflattens them back, mirroring the npm "flat" library.
Flattening turns a tree such as {"a": {"b": 1}} into the single-level map {"a.b": 1}, and unflattening reverses the process. This is convenient when a nested structure must be projected onto a flat key space: environment variables, form fields, dot-notation config, database columns, or any store that only accepts string keys and scalar values.
Flatten walks the input recursively. For every value that is itself a map[string]any it descends, joining each level's key to the accumulated prefix with the delimiter (default "."); any other value, including a slice or a struct, is stored unchanged as a leaf. Unflatten performs the inverse: it splits each composite key on the delimiter and rebuilds the nested maps segment by segment. The delimiter is configurable through FlattenOpts and UnflattenOpts, but both sides must agree on it for a round trip to succeed.
One deliberate edge case is that an empty nested map is preserved as a leaf rather than vanishing, so {"a": {}} flattens to {"a": {}} with the empty map intact; this keeps Flatten followed by Unflatten a faithful round trip for map-only data. An empty top-level map flattens to an empty map. There is no configurable depth limit: Flatten always descends to the bottom of the map tree, and Unflatten always rebuilds the full nesting implied by the keys.
Because Go maps use string keys and carry no notion of arrays, this port operates purely on map[string]any and does not attempt the array handling, key transformation, safe/overwrite, or maxDepth options of the JavaScript original. Values that are not map[string]any, including slices, are treated as opaque leaves. Neither function returns an error; malformed keys simply produce whatever nesting the delimiter split implies.
Index ¶
Examples ¶
Constants ¶
const DefaultDelimiter = "."
DefaultDelimiter is the key separator used when none is configured.
Variables ¶
This section is empty.
Functions ¶
func Flatten ¶
func Flatten(m map[string]any, opts ...FlattenOpts) map[string]any
Flatten recursively flattens a nested map into a single-level map whose keys are joined by the configured delimiter (default "."). Non-map leaf values, including empty maps, are preserved as-is.
Example ¶
ExampleFlatten collapses a nested map into a single-level map whose keys are joined by the default "." delimiter. The function descends into every value that is itself a map[string]any, concatenating each level's key onto the accumulated prefix. Scalar values such as the integers here are stored unchanged as leaves. The output is printed with fmt, which sorts map keys, so the ordering is deterministic. Note how the two-level path a -> b becomes the composite key "a.b".
package main
import (
"fmt"
"github.com/malcolmston/express/flat"
)
func main() {
in := map[string]any{
"a": map[string]any{"b": 1, "c": 2},
"d": 3,
}
fmt.Println(flat.Flatten(in))
}
Output: map[a.b:1 a.c:2 d:3]
Example (CustomDelimiter) ¶
ExampleFlatten_customDelimiter overrides the default separator through FlattenOpts. Passing a Delimiter of "/" makes the flattened keys use slashes instead of dots, which is convenient when the target key space already uses a path-like convention. Every nested level is joined with the chosen delimiter. The same delimiter must be supplied to Unflatten to reverse the operation. Here the nested a -> b path becomes "a/b".
package main
import (
"fmt"
"github.com/malcolmston/express/flat"
)
func main() {
in := map[string]any{"a": map[string]any{"b": 1}}
fmt.Println(flat.Flatten(in, flat.FlattenOpts{Delimiter: "/"}))
}
Output: map[a/b:1]
func Unflatten ¶
func Unflatten(m map[string]any, opts ...UnflattenOpts) map[string]any
Unflatten expands a single-level map with delimited keys back into a nested map structure. It inverts Flatten for map[string]any inputs.
Example ¶
ExampleUnflatten reverses Flatten, expanding delimited keys back into a nested map structure. Each composite key is split on the delimiter and the nested maps are rebuilt segment by segment. Keys that share a prefix are merged into the same parent map, so "a.b" and "a.c" both live under "a". The result is printed with fmt, which sorts keys recursively for a stable rendering. This makes Unflatten the inverse of Flatten for map-only data.
package main
import (
"fmt"
"github.com/malcolmston/express/flat"
)
func main() {
in := map[string]any{"a.b": 1, "a.c": 2, "d": 3}
fmt.Println(flat.Unflatten(in))
}
Output: map[a:map[b:1 c:2] d:3]
Types ¶
type FlattenOpts ¶
type FlattenOpts struct {
// Delimiter separates nested key segments. Defaults to ".".
Delimiter string
}
FlattenOpts configures Flatten.
type UnflattenOpts ¶
type UnflattenOpts struct {
// Delimiter separates nested key segments. Defaults to ".".
Delimiter string
}
UnflattenOpts configures Unflatten.