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 structs
Works 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/
- ...
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
package main
import (
"encoding/json""fmt""log""github.com/ompluscator/dynamic-struct"
)
funcmain() {
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)
iferr!=nil {
log.Fatal(err)
}
data, err=json.Marshal(instance)
iferr!=nil {
log.Fatal(err)
}
fmt.Println(string(data))
// Out:// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
}package main
import (
"encoding/json""fmt""log""github.com/ompluscator/dynamic-struct"
)
typeDatastruct {
Integerint`json:"int"`
}
funcmain() {
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)
iferr!=nil {
log.Fatal(err)
}
data, err=json.Marshal(instance)
iferr!=nil {
log.Fatal(err)
}
fmt.Println(string(data))
// Out:// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
}package main
import (
"encoding/json""fmt""log""github.com/ompluscator/dynamic-struct"
)
typeDataOnestruct {
Integerint`json:"int"`Textstring`json:"someText"`Floatfloat64`json:"double"`
}
typeDataTwostruct {
BooleanboolSlice []intAnonymousstring`json:"-"`
}
funcmain() {
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)
iferr!=nil {
log.Fatal(err)
}
data, err=json.Marshal(instance)
iferr!=nil {
log.Fatal(err)
}
fmt.Println(string(data))
// Out:// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
}package main
import (
"encoding/json""fmt""log""github.com/ompluscator/dynamic-struct"
)
typeDataOnestruct {
Integerint`json:"int"`Textstring`json:"someText"`Floatfloat64`json:"double"`
}
typeDataTwostruct {
BooleanboolSlice []intAnonymousstring`json:"-"`
}
funcmain() {
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)
iferr!=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())
vardataOneDataOneerr=reader.ToStruct(&dataOne)
fmt.Println(err, dataOne)
vardataTwoDataTwoerr=reader.ToStruct(&dataTwo)
fmt.Println(err, dataTwo)
// Out:// Integer 123// Text example// Float 123.45// Boolean true// Slice [1 2 3]// Anonymous// <nil> {123 example 123.45}// <nil> {true [1 2 3] }
}package main
import (
"encoding/json""fmt""log""github.com/ompluscator/dynamic-struct"
)
typeDatastruct {
Integerint`json:"int"`Textstring`json:"someText"`Floatfloat64`json:"double"`BooleanboolSlice []intAnonymousstring`json:"-"`
}
funcmain() {
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)
iferr!=nil {
log.Fatal(err)
}
data, err=json.Marshal(slice)
iferr!=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()
fork, v:=rangereadersSlice {
varvalueDataerr:=v.ToStruct(&value)
iferr!=nil {
log.Fatal(err)
}
fmt.Println(k, value)
}
// Out:// 0 {123 example 123.45 true [1 2 3] }
}package main
import (
"encoding/json""fmt""log""github.com/ompluscator/dynamic-struct"
)
typeDatastruct {
Integerint`json:"int"`Textstring`json:"someText"`Floatfloat64`json:"double"`BooleanboolSlice []intAnonymousstring`json:"-"`
}
funcmain() {
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)
iferr!=nil {
log.Fatal(err)
}
data, err=json.Marshal(mapWithStringKey)
iferr!=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()
fork, v:=rangereadersMap {
varvalueDataerr:=v.ToStruct(&value)
iferr!=nil {
log.Fatal(err)
}
fmt.Println(k, value)
}
// Out:// element {123 example 123.45 true [1 2 3] }
}