Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ompluscator/dynamic-struct
Golang package for editing struct's fields during runtime and mapping structs to other structs.
https://github.com/ompluscator/dynamic-struct
dynamic go golang runtime structs
Last synced: 1 day ago
JSON representation
Golang package for editing struct's fields during runtime and mapping structs to other structs.
- Host: GitHub
- URL: https://github.com/ompluscator/dynamic-struct
- Owner: Ompluscator
- License: mit
- Created: 2019-01-04T19:44:40.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2024-01-27T21:54:19.000Z (10 months ago)
- Last Synced: 2024-06-19T12:46:21.850Z (5 months ago)
- Topics: dynamic, go, golang, runtime, structs
- Language: Go
- Homepage:
- Size: 43 KB
- Stars: 670
- Watchers: 26
- Forks: 82
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![Go Reference](https://pkg.go.dev/badge/github.com/Ompluscator/dynamic-struct.svg)](https://pkg.go.dev/github.com/Ompluscator/dynamic-struct)
![Coverage](https://img.shields.io/badge/Coverage-92.6%25-brightgreen)
[![Go Report Card](https://goreportcard.com/badge/github.com/ompluscator/dynamic-struct)](https://goreportcard.com/report/github.com/ompluscator/dynamic-struct)# Golang dynamic struct
Package dynamic struct provides possibility to dynamically, in runtime,
extend or merge existing defined structs or to provide completely new struct.Main features:
* Building completely new struct in runtime
* Extending existing struct in runtime
* Merging multiple structs in runtime
* Adding new fields into struct
* Removing existing fields from struct
* Modifying fields' types and tags
* Easy reading of dynamic structs
* Mapping dynamic struct with set values to existing struct
* Make slices and maps of dynamic structsWorks out-of-the-box with:
* https://github.com/go-playground/form
* https://github.com/go-playground/validator
* https://github.com/leebenson/conform
* https://golang.org/pkg/encoding/json/
* ...## Benchmarks
Environment:
* MacBook Pro (13-inch, Early 2015), 2,7 GHz Intel Core i5
* go version go1.11 darwin/amd64```
goos: darwin
goarch: amd64
pkg: github.com/ompluscator/dynamic-struct
BenchmarkClassicWay_NewInstance-4 2000000000 0.34 ns/op
BenchmarkNewStruct_NewInstance-4 10000000 141 ns/op
BenchmarkNewStruct_NewInstance_Parallel-4 20000000 89.6 ns/op
BenchmarkExtendStruct_NewInstance-4 10000000 135 ns/op
BenchmarkExtendStruct_NewInstance_Parallel-4 20000000 89.5 ns/op
BenchmarkMergeStructs_NewInstance-4 10000000 140 ns/op
BenchmarkMergeStructs_NewInstance_Parallel-4 20000000 94.3 ns/op
```## Add new struct
```go
package mainimport (
"encoding/json"
"fmt"
"log""github.com/ompluscator/dynamic-struct"
)func main() {
instance := dynamicstruct.NewStruct().
AddField("Integer", 0, `json:"int"`).
AddField("Text", "", `json:"someText"`).
AddField("Float", 0.0, `json:"double"`).
AddField("Boolean", false, "").
AddField("Slice", []int{}, "").
AddField("Anonymous", "", `json:"-"`).
Build().
New()data := []byte(`
{
"int": 123,
"someText": "example",
"double": 123.45,
"Boolean": true,
"Slice": [1, 2, 3],
"Anonymous": "avoid to read"
}
`)err := json.Unmarshal(data, &instance)
if err != nil {
log.Fatal(err)
}data, err = json.Marshal(instance)
if err != nil {
log.Fatal(err)
}fmt.Println(string(data))
// Out:
// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
}
```## Extend existing struct
```go
package mainimport (
"encoding/json"
"fmt"
"log""github.com/ompluscator/dynamic-struct"
)type Data struct {
Integer int `json:"int"`
}func main() {
instance := dynamicstruct.ExtendStruct(Data{}).
AddField("Text", "", `json:"someText"`).
AddField("Float", 0.0, `json:"double"`).
AddField("Boolean", false, "").
AddField("Slice", []int{}, "").
AddField("Anonymous", "", `json:"-"`).
Build().
New()data := []byte(`
{
"int": 123,
"someText": "example",
"double": 123.45,
"Boolean": true,
"Slice": [1, 2, 3],
"Anonymous": "avoid to read"
}
`)err := json.Unmarshal(data, &instance)
if err != nil {
log.Fatal(err)
}data, err = json.Marshal(instance)
if err != nil {
log.Fatal(err)
}fmt.Println(string(data))
// Out:
// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
}
```## Merge existing structs
```go
package mainimport (
"encoding/json"
"fmt"
"log""github.com/ompluscator/dynamic-struct"
)type DataOne struct {
Integer int `json:"int"`
Text string `json:"someText"`
Float float64 `json:"double"`
}type DataTwo struct {
Boolean bool
Slice []int
Anonymous string `json:"-"`
}func main() {
instance := dynamicstruct.MergeStructs(DataOne{}, DataTwo{}).
Build().
New()data := []byte(`
{
"int": 123,
"someText": "example",
"double": 123.45,
"Boolean": true,
"Slice": [1, 2, 3],
"Anonymous": "avoid to read"
}
`)err := json.Unmarshal(data, &instance)
if err != nil {
log.Fatal(err)
}data, err = json.Marshal(instance)
if err != nil {
log.Fatal(err)
}fmt.Println(string(data))
// Out:
// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
}
```## Read dynamic struct
```go
package mainimport (
"encoding/json"
"fmt"
"log""github.com/ompluscator/dynamic-struct"
)type DataOne struct {
Integer int `json:"int"`
Text string `json:"someText"`
Float float64 `json:"double"`
}type DataTwo struct {
Boolean bool
Slice []int
Anonymous string `json:"-"`
}func main() {
instance := dynamicstruct.MergeStructs(DataOne{}, DataTwo{}).
Build().
New()data := []byte(`
{
"int": 123,
"someText": "example",
"double": 123.45,
"Boolean": true,
"Slice": [1, 2, 3],
"Anonymous": "avoid to read"
}
`)err := json.Unmarshal(data, &instance)
if err != nil {
log.Fatal(err)
}reader := dynamicstruct.NewReader(instance)
fmt.Println("Integer", reader.GetField("Integer").Int())
fmt.Println("Text", reader.GetField("Text").String())
fmt.Println("Float", reader.GetField("Float").Float64())
fmt.Println("Boolean", reader.GetField("Boolean").Bool())
fmt.Println("Slice", reader.GetField("Slice").Interface().([]int))
fmt.Println("Anonymous", reader.GetField("Anonymous").String())var dataOne DataOne
err = reader.ToStruct(&dataOne)
fmt.Println(err, dataOne)var dataTwo DataTwo
err = reader.ToStruct(&dataTwo)
fmt.Println(err, dataTwo)
// Out:
// Integer 123
// Text example
// Float 123.45
// Boolean true
// Slice [1 2 3]
// Anonymous
// {123 example 123.45}
// {true [1 2 3] }
}
```## Make a slice of dynamic struct
```go
package mainimport (
"encoding/json"
"fmt"
"log""github.com/ompluscator/dynamic-struct"
)type Data struct {
Integer int `json:"int"`
Text string `json:"someText"`
Float float64 `json:"double"`
Boolean bool
Slice []int
Anonymous string `json:"-"`
}func main() {
definition := dynamicstruct.ExtendStruct(Data{}).Build()slice := definition.NewSliceOfStructs()
data := []byte(`
[
{
"int": 123,
"someText": "example",
"double": 123.45,
"Boolean": true,
"Slice": [1, 2, 3],
"Anonymous": "avoid to read"
}
]
`)err := json.Unmarshal(data, &slice)
if err != nil {
log.Fatal(err)
}data, err = json.Marshal(slice)
if err != nil {
log.Fatal(err)
}fmt.Println(string(data))
// Out:
// [{"Boolean":true,"Slice":[1,2,3],"int":123,"someText":"example","double":123.45}]reader := dynamicstruct.NewReader(slice)
readersSlice := reader.ToSliceOfReaders()
for k, v := range readersSlice {
var value Data
err := v.ToStruct(&value)
if err != nil {
log.Fatal(err)
}fmt.Println(k, value)
}
// Out:
// 0 {123 example 123.45 true [1 2 3] }
}```
## Make a map of dynamic struct
```go
package mainimport (
"encoding/json"
"fmt"
"log""github.com/ompluscator/dynamic-struct"
)type Data struct {
Integer int `json:"int"`
Text string `json:"someText"`
Float float64 `json:"double"`
Boolean bool
Slice []int
Anonymous string `json:"-"`
}func main() {
definition := dynamicstruct.ExtendStruct(Data{}).Build()mapWithStringKey := definition.NewMapOfStructs("")
data := []byte(`
{
"element": {
"int": 123,
"someText": "example",
"double": 123.45,
"Boolean": true,
"Slice": [1, 2, 3],
"Anonymous": "avoid to read"
}
}
`)err := json.Unmarshal(data, &mapWithStringKey)
if err != nil {
log.Fatal(err)
}data, err = json.Marshal(mapWithStringKey)
if err != nil {
log.Fatal(err)
}fmt.Println(string(data))
// Out:
// {"element":{"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}}reader := dynamicstruct.NewReader(mapWithStringKey)
readersMap := reader.ToMapReaderOfReaders()
for k, v := range readersMap {
var value Data
err := v.ToStruct(&value)
if err != nil {
log.Fatal(err)
}fmt.Println(k, value)
}
// Out:
// element {123 example 123.45 true [1 2 3] }
}```