barky

package module
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2025 License: Apache-2.0 Imports: 8 Imported by: 1

README

Barky

English | 中文

Barky is a Go package for managing hierarchical key-value data structures, mainly designed for configuration files such as JSON, YAML, and TOML. It can flatten nested data structures into a map[string]string while preserving path information, detecting conflicts, and tracking multi-file sources.

✨ Key Features

1. Flattening
  • Supports converting nested map, slice, and array into a flat map[string]string.
  • Uses dots to denote map keys and brackets to denote array/slice indices.
2. Path Handling
  • The Path type parses hierarchical keys into a sequence of path segments (map keys or array indices).
  • Provides SplitPath to convert "foo.bar[0]" into structured path segments, and JoinPath to join path segments back into a string.
  • Performs syntax validation to prevent invalid keys (e.g., consecutive dots, unclosed brackets).
3. Storage
  • The Storage type manages a set of flattened key-value pairs and builds an internal tree to detect structural conflicts.

  • Each value is associated with a source file index, making it easy to track origins when merging multiple files.

  • Key methods include:

    • Set: Set a key-value pair with conflict detection.
    • Get: Retrieve a value, optionally providing a default.
    • Has: Check whether a key exists.
    • SubKeys: List subkeys under a given path.
    • Keys: Get all stored keys in sorted order.

📦 Installation

go get github.com/go-spring/barky

🛠 Usage Example

package main

import (
	"fmt"
	"github.com/go-spring/barky"
)

func main() {
	s := barky.NewStorage()
	fileIdx := s.AddFile("config.yaml")

	_ = s.Set("server.hosts[0].ip", "192.168.0.1", fileIdx)
	_ = s.Set("server.hosts[1].ip", "192.168.0.2", fileIdx)

	fmt.Println("Keys:", s.Keys())
	fmt.Println("SubKeys of server.hosts:", s.SubKeys("server.hosts"))
	fmt.Println("Get server.hosts[0].ip:", s.Get("server.hosts[0].ip"))
}

Output:

Keys: [server.hosts[0].ip server.hosts[1].ip]
SubKeys of server.hosts: [0 1]
Get server.hosts[0].ip: 192.168.0.1

📖 Use Cases

  • Configuration Management Convert configuration files of various formats into a unified flat key-value map for easier comparison and merging.

  • Querying & Retrieval Access nested data directly using simple path strings like "server.hosts[0].ip", without manually traversing the structure.

  • Multi-File Merging Handle multiple configuration files at once, track the source of each key, and detect conflicts.

  • Data Transformation Flatten hierarchical structures for easier processing in testing, diffing, or downstream systems.

⚠️ Notes

  • Paths must not contain spaces, consecutive dots, unclosed brackets, or other invalid formats.
  • Type conflicts in the tree structure (e.g., "user.name" vs "user[0]") will return an error.
  • RawData and RawFile expose internal storage directly—use with caution.

📜 License

Apache 2.0 License

Documentation

Overview

Package barky provides utilities for handling hierarchical key/value data structures that commonly appear in configuration formats such as JSON, YAML, or TOML. It is designed to transform nested data into a flat representation, while preserving enough metadata to reconstruct paths, detect conflicts, and manage data from multiple sources.

Key features include:

  • Flattening: Nested maps, slices, and arrays can be converted into a flat map[string]string using dot notation for maps and index notation for arrays/slices. For example, {"db": {"hosts": ["a", "b"]}} becomes {"db.hosts[0]": "a", "db.hosts[1]": "b"}.

  • Path handling: The package defines a Path abstraction that represents hierarchical keys as a sequence of typed segments (map keys or array indices). Paths can be split from strings like "foo.bar[0]" or joined back into their string form.

  • Storage: A Storage type manages a collection of flattened key/value pairs. It builds and maintains a hierarchical tree internally to prevent property conflicts (e.g., treating the same key as both a map and a value). Storage also associates values with the files they originated from, which allows multi-file merging and provenance tracking.

  • Querying: The Storage type provides helper methods for retrieving values, checking for the existence of keys, enumerating subkeys, and iterating in a deterministic order.

Typical use cases:

  • Normalizing configuration files from different sources into a flat key/value map for comparison, merging, or diffing.
  • Querying nested data using simple string paths without dealing with reflection or nested map structures directly.
  • Building tools that need to unify structured data from multiple files while preserving provenance information and preventing conflicts.

Overall, barky acts as a bridge between deeply nested structured data and flat, queryable representations that are easier to work with in configuration management, testing, or data transformation pipelines.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FlattenMap

func FlattenMap(m map[string]any) map[string]string

FlattenMap takes a nested map[string]any and flattens it into a map[string]string where nested structures are represented using dot-notation (for maps) and index-notation (for slices/arrays). Nil values are skipped, and empty maps/slices are represented as empty strings.

func FlattenValue

func FlattenValue(key string, val any, result map[string]string)

FlattenValue is a recursive helper function that processes a value (map, slice, array, or primitive) and stores its flattened representation into the result map under the given key. Nested structures are expanded using dot/index notation.

func JoinPath

func JoinPath(path []Path) string

JoinPath converts a slice of Path objects into a string representation. Keys are joined with dots, and array indices are wrapped in square brackets. Example: [key, index(0), key] => "key[0].key".

func OrderedMapKeys

func OrderedMapKeys[M ~map[K]V, K cmp.Ordered, V any](m M) []K

OrderedMapKeys returns the sorted keys of a generic map with ordered keys. It is a utility function used to provide deterministic ordering of map keys.

Types

type Path

type Path struct {
	// Whether the element is a key or an index.
	Type PathType

	// Actual key or index value as a string.
	// For PathTypeKey, it's the key string;
	// for PathTypeIndex, it's the index number as a string.
	Elem string
}

Path represents a single segment in a parsed key path. A path is composed of multiple Path elements that can be joined or split. For example, "foo.bar[0]" would parse into: [{Key: "foo"}, {Key: "bar"}, {Index: "0"}].

func SplitPath

func SplitPath(key string) (_ []Path, err error)

SplitPath parses a string key path into a slice of Path objects. It supports dot-notation for maps and bracket-notation for arrays. Returns an error if the key is malformed (e.g., consecutive dots, unbalanced brackets).

type PathType

type PathType int8

PathType represents the type of a path element in a hierarchical key. A path element can either be a key (map field) or an index (array/slice element).

const (
	PathTypeKey   PathType = iota // A named key in a map.
	PathTypeIndex                 // A numeric index in a list.
)

type Storage

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

Storage manages a collection of flattened key/value pairs while preserving hierarchical structure for validation and queries. It tracks both values and the files they come from, and prevents structural conflicts when setting values.

func NewStorage

func NewStorage() *Storage

NewStorage creates a new Storage instance.

func (*Storage) AddFile

func (s *Storage) AddFile(file string) int8

AddFile registers a file name into the storage, assigning it a unique int8 index if it has not been added before. Returns the index of the file.

func (*Storage) Data

func (s *Storage) Data() map[string]string

Data returns a simplified map of flattened key → string value, discarding file index information.

func (*Storage) Get

func (s *Storage) Get(key string, def ...string) string

Get retrieves the value associated with a key. If the key is not found and a default value is provided, the default is returned instead.

func (*Storage) Has

func (s *Storage) Has(key string) bool

Has checks whether a key (or nested structure) exists in the storage. Returns false if the key is invalid or conflicts with existing structure.

func (*Storage) Keys

func (s *Storage) Keys() []string

Keys returns all flattened keys currently stored, sorted in lexicographic order.

func (*Storage) RawData

func (s *Storage) RawData() map[string]ValueInfo

RawData returns the internal map of flattened key → ValueInfo, Warning: exposes internal state directly.

func (*Storage) RawFile

func (s *Storage) RawFile() map[string]int8

RawFile returns the internal mapping of file names to their assigned indexes. Warning: exposes internal state directly.

func (*Storage) Set

func (s *Storage) Set(key string, val string, file int8) error

Set inserts or updates a key with the given value and file index. It ensures that the key path is valid and does not conflict with existing structure types. Returns an error if conflicts are detected.

func (*Storage) SubKeys

func (s *Storage) SubKeys(key string) (_ []string, err error)

SubKeys retrieves the immediate child keys under the given path. For example, given "a.b", it returns the keys directly under "a.b". Returns an error if the path is invalid or conflicts exist.

type ValueInfo

type ValueInfo struct {
	File  int8
	Value string
}

ValueInfo stores metadata about a flattened value in Storage. It includes both the string value and the file index that the value originated from.

Jump to

Keyboard shortcuts

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