Categorygithub.com/brynbellomy/go-structomancer
modulepackage
1.0.3
Repository: https://github.com/brynbellomy/go-structomancer.git
Documentation: pkg.go.dev

# README

structomancer

Golang struct reflection package. Primarily aimed at package authors who want to add struct tag functionality and/or struct serialization and deserialization to their packages.

fast

structomancer is pretty fast. A lot of the reflection calls it makes are only performed once per type, and are fetched from a sync.RWMutex-protected cache on subsequent lookups.

what you can do

import "github.com/brynbellomy/go-structomancer"

type Blah struct {
    Name      string      `api:"name"                 db:"name"`
    Token     int         `api:"token"                db:"-"`
    SessionID string      `api:"-"                    db:"-"`
    Inner     InnerStruct `api:"inner, @tag=weezy"    db:"inner_struct"`
}

type InnerStruct struct {
    Quux string `weezy:"quux"`
}

func main() {
    z := structomancer.New(&Blah{}, "api") // provide a specimen struct and the struct tag

    //
    // deserialize a map to a struct
    //
    s, err := z.MapToStruct(map[string]interface{}{
        "name": "xyzzy",
        "token": 123,
        "inner": map[string]interface{}{
            "quux": "asdf",
        },
    })

    //
    // serialize a struct to a map
    //
    m, err := z.StructToMap(&Blah{
        Name: "xyzzy",
        Token: 123,
        Inner: InnerStruct{Quux: "asdf"},
    })

    //
    // generate empty, addressable instances of a type
    //
    x := z.MakeEmpty()                           // returns a &Blah{}
    structomancer.New(Blah{}, "api").MakeEmpty() // also returns a &Blah

    //
    // validate fields based on struct tags
    //
    z.IsKnownField("inner")        // returns true
    z.IsKnownField("sessionID")    // returns false

    //
    // get field values
    //
    blah := &Blah{Name: "foobar"}
    v, err := z.GetFieldValue(blah, "name")  // returns "foobar", nil

    //
    // set field values
    //
    err := z.SetFieldValue(blah, "name", "qaax")
}

custom decoding/encoding

You might find that you need to set up custom serializer/deserializer functions for individual fields (for example, fields with interface types, which cannot be automatically deserialized by structomancer).

Doing so is easy:

type IFooer interface{ Foo() }

type Blah struct {
    Fooers []IFooer `api:"fooers"`
}

func main() {
    z := structomancer.New(&Blah{}, "api")

    z.SetFieldEncoder("fooers", func(x interface{}) (interface{}, error) {
        fooers := x.([]IFooer)
        // ... convert from []IFooer to []interface{} ...
        return fs, nil
    })

    z.SetFieldDecoder("fooers", func(x interface{}) (interface{}, error) {
        fs := x.([]interface{})
        // ... convert from []interface{} to []IFooer ...
        return fooers, nil
    })

    // now, your (de)serializers will run when you call the following methods:
    z.StructToMap(...)
    z.MapToStruct(...)
}

reflect package compatibility

If you're working with lots of reflect.Values already, you probably want to avoid creating even more of them (reflection is apparently expensive because of allocations, although I forget where I read that).

To avoid unnecessary boxing/unboxing of your values, you can access all of structomancer's methods via an alternate reflect.Value-compatible interface:

.MakeEmptyV() reflect.Value
.GetFieldValueV(v reflect.Value, fnickname string) (reflect.Value, error)
.SetFieldValueV(sv reflect.Value, fname string, value reflect.Value) error
.StructToMapV(aStruct reflect.Value) (map[string]interface{}, error)
.MapToStructV(fields map[string]interface{}) (reflect.Value, error)

Should be substantially faster, but I haven't profiled it yet.

authors/contributors

# Functions

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author
No description provided by the author

# Interfaces

No description provided by the author

# Type aliases

No description provided by the author