A Go library for creating a normalized and flattened representation of any value. Perfect for data comparison, serialization, and deep structure analysis.
- Flatten Any Type: Support for primitives, arrays, maps, structs, and deeply nested structures
- Field Filtering: Include or exclude specific fields using options
- Deep Comparison: Compare complex structures regardless of order
- Type Safe: Works with Go's type system using reflection
- Sorted Output: Results are consistently sorted for reliable comparisons
go get github.com/go-universal/flattenpackage main
import (
"fmt"
"github.com/go-universal/flatten"
)
type User struct {
ID int
Name string
Email string
age int // unexported fields are ignored
}
func main() {
user := User{
ID: 1,
Name: "Alice",
Email: "alice@example.com",
age: 30,
}
result := flatten.Flatten(user)
for _, item := range result {
fmt.Println(item)
}
// Output:
// Email:alice@example.com
// ID:1
// Name:Alice
}// Include only specific fields
result := flatten.Flatten(user, flatten.WithIncludeFields("ID", "Name"))
// Result: [ID:1 Name:Alice]
// Exclude specific fields
result := flatten.Flatten(user, flatten.WithExcludeFields("Email"))
// Result: [ID:1 Name:Alice]user1 := User{ID: 1, Name: "Alice", Email: "alice@example.com"}
user2 := User{ID: 1, Name: "Alice", Email: "alice@example.com"}
// Compare all fields
isEqual := flatten.FlattenCompare(user1, user2)
fmt.Println(isEqual) // true
// Compare with excluded fields
user3 := User{ID: 1, Name: "Alice", Email: "different@example.com"}
isEqual = flatten.FlattenCompare(user1, user3, flatten.WithExcludeFields("Email"))
fmt.Println(isEqual) // true- Primitives: string, int, uint, float64, bool, nil
- Collections: arrays, slices, maps
- Structures: structs with exported fields
- Nested: arbitrary depth of nested types
The library recursively traverses your data structure and generates a flat list of key-value pairs:
type Person struct {
Name string
Address struct {
City string
Zip string
}
}
person := Person{
Name: "Bob",
Address: struct {
City string
Zip string
}{
City: "NYC",
Zip: "10001",
},
}
result := flatten.Flatten(person)
// Output:
// Address.City:NYC
// Address.Zip:10001
// Name:Bobfunc Flatten(value any, options ...Options) []stringFlattens any value into a sorted slice of strings. Each string represents a flattened key-value pair in the format key:value.
Parameters:
value: The value to flatten (any type)options: Optional configuration functions
Returns: Sorted slice of flattened strings
func FlattenCompare(src, dest any, options ...Options) boolCompares two values by flattening them and checking for equality.
Parameters:
src: Source value to comparedest: Destination value to compareoptions: Optional configuration functions
Returns: true if both values flatten to the same representation
flatten.WithIncludeFields(fields ...string) OptionsIncludes only specified fields in the flattening result.
flatten.WithExcludeFields(fields ...string) OptionsExcludes specified fields from the flattening result.
type Company struct {
Name string
Employees []struct {
ID int
Name string
}
}
company := Company{
Name: "TechCorp",
Employees: []struct {
ID int
Name string
}{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
},
}
result := flatten.Flatten(company)
// Output:
// Employees.ID:1
// Employees.ID:2
// Employees.Name:Alice
// Employees.Name:Bob
// Name:TechCorptype Document struct {
Title string
Content string
ModifiedAt time.Time
}
doc1 := Document{Title: "Report", Content: "Data", ModifiedAt: time.Now()}
doc2 := Document{Title: "Report", Content: "Data", ModifiedAt: time.Now().Add(1 * time.Hour)}
// Compare documents ignoring the timestamp
isEqual := flatten.FlattenCompare(doc1, doc2, flatten.WithExcludeFields("ModifiedAt"))
fmt.Println(isEqual) // trueThis project is licensed under the ISC License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.