Skip to content

viant/structology

Repository files navigation

structology - State tracker for golang struct

GoReportCard GoDoc

This library is compatible with Go 1.17+

Please refer to CHANGELOG.md if you encounter breaking changes.

Motivation

This project defines struct field set marker to distinctively identify input state, specifically for 'empty', 'nil', 'has been set' state. This is critical for update/patch operation with large struct where only small subset if defined, with presence marker allowing you handling user input effectively, ensuring data integrity, and improving the security of applications

Initially we have a few project holding marker abstraction to finally move it to this project.

This project also implement a state that wraps arbitrary go struct, and provide selectors to dynamically access/mutate any nested/addressable values, if set marker is defined all set operation also would flag respective marker field

Usage

Set Marker
type (
    HasEntity struct {
	    Id     bool
        Name   bool
        Active bool
	}
     Entity struct {
        Id     int
        Name   string
        Active bool
        Has    *EntityHas `setMarker:"true"`
    }
)

    var entity *Entity

	....// load entity and set all present fields with marker.Set(...)

	
    marker, err := NewMarker()
    if err != nil {
        log.Fatal(err)
    }
    isIdSet := marker.IsSet(marker.Index("Id"))
	fmt.Printf("is ID set : %v\n", isIdSet)
	
}
State with SetMarker
package bar

import (
	"fmt"
	"reflect"
	"github.com/viant/structology"
	"encoding/json"
)

type FooHas struct {
	Id   bool
	Name bool
}

type DummyHas struct {
	Id  bool
	Foo bool
}

type Foo struct {
	Id   int
	Name string
	Has  *FooHas `setMarker:"true"`
}

type Dummy struct {
	Id  int
	Foo *Foo
	Has *DummyHas `setMarker:"true"`
}

func ShowStateUsage() {
	
	dummy := &Dummy{Foo: &Foo{}}
	valueType := reflect.TypeOf(dummy)
	stateType := structology.NewStateType(valueType)
	state := stateType.WithValue(dummy)
	
	hasFoo, _ := state.Bool("Has.Foo")
	fmt.Printf("initial foo has marker: %v\n", 	hasFoo)
	hasFooName, _ := 	state.Bool("Foo.Has.Name") 
	fmt.Printf("initial foo has marker: %v\n", 	hasFooName)
	
	state.SetString("Foo.Name", "Bob Dummy")
	data, _ := json.Marshal(dummy)
	fmt.Printf("dummy: %s\n", data)

	hasFoo, _ = state.Bool("Has.Foo")
	fmt.Printf("foo has marker: %v\n", 	hasFoo)
	hasFooName, _ = 	state.Bool("Foo.Has.Name")
	fmt.Printf("foo has marker: %v\n", 	hasFooName)
	
}

Check unit test for more advanced usage.

Contributing to structology

structology is an open source project and contributors are welcome!

See TODO list

License

The source code is made available under the terms of the Apache License, Version 2, as stated in the file LICENSE.

Individual files may be made available under their own specific license, all compatible with Apache License, Version 2. Please see individual files for details.

Credits and Acknowledgements

Library Author: Adrian Witas