Skip to content

A Go library for creating a normalized and flattened representation of any value. Perfect for data comparison, serialization, and deep structure analysis.

License

Notifications You must be signed in to change notification settings

go-universal/flatten

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go Flatten Library

GitHub Tag Go Reference License Go Report Card Contributors Issues

A Go library for creating a normalized and flattened representation of any value. Perfect for data comparison, serialization, and deep structure analysis.

Features

  • 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

Installation

go get github.com/go-universal/flatten

Quick Start

Basic Flattening

package 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
}

Filtering Fields

// 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]

Comparing Structures

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

Supported Types

  • Primitives: string, int, uint, float64, bool, nil
  • Collections: arrays, slices, maps
  • Structures: structs with exported fields
  • Nested: arbitrary depth of nested types

How It Works

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:Bob

API Reference

Flatten

func Flatten(value any, options ...Options) []string

Flattens 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

FlattenCompare

func FlattenCompare(src, dest any, options ...Options) bool

Compares two values by flattening them and checking for equality.

Parameters:

  • src: Source value to compare
  • dest: Destination value to compare
  • options: Optional configuration functions

Returns: true if both values flatten to the same representation

Options

WithIncludeFields

flatten.WithIncludeFields(fields ...string) Options

Includes only specified fields in the flattening result.

WithExcludeFields

flatten.WithExcludeFields(fields ...string) Options

Excludes specified fields from the flattening result.

Examples

Example 1: Flatten Complex Nested Structure

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:TechCorp

Example 2: Compare Structures Ignoring Timestamps

type 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) // true

License

This project is licensed under the ISC License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

About

A Go library for creating a normalized and flattened representation of any value. Perfect for data comparison, serialization, and deep structure analysis.

Resources

License

Stars

Watchers

Forks

Languages