Ompluscator
dynamic-struct
Go

Golang package for editing struct's fields during runtime and mapping structs to other structs.

Last updated Jun 17, 2026
729
Stars
80
Forks
3
Issues
0
Stars/day
Attention Score
30
Language breakdown
Go 100.0%
Files click to expand
README

Go Reference Coverage Go Report Card

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 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/
  • ...

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 BenchmarkNewStructNewInstanceParallel-4           20000000     89.6 ns/op BenchmarkExtendStruct_NewInstance-4                 10000000      135 ns/op BenchmarkExtendStructNewInstanceParallel-4        20000000     89.5 ns/op BenchmarkMergeStructs_NewInstance-4                 10000000      140 ns/op BenchmarkMergeStructsNewInstanceParallel-4        20000000     94.3 ns/op

Add new struct

package main

import ( "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

package main

import ( "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

package main

import ( "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

package main

import ( "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 // <nil> {123 example 123.45} // <nil> {true [1 2 3] } }

Make a slice of dynamic struct

package main

import ( "encoding/json" "fmt" "log"

"github.com/ompluscator/dynamic-struct" )

type Data struct { Integer int json:&quot;int&quot; Text string json:&quot;someText&quot; Float float64 json:&quot;double&quot; Boolean bool Slice []int Anonymous string json:&quot;-&quot; }

func main() { definition := dynamicstruct.ExtendStruct(Data{}).Build()

slice := definition.NewSliceOfStructs()

data := []byte( [ { &quot;int&quot;: 123, &quot;someText&quot;: &quot;example&quot;, &quot;double&quot;: 123.45, &quot;Boolean&quot;: true, &quot;Slice&quot;: [1, 2, 3], &quot;Anonymous&quot;: &quot;avoid to read&quot; } ] )

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

package main

import ( "encoding/json" "fmt" "log"

"github.com/ompluscator/dynamic-struct" )

type Data struct { Integer int json:&quot;int&quot; Text string json:&quot;someText&quot; Float float64 json:&quot;double&quot; Boolean bool Slice []int Anonymous string json:&quot;-&quot; }

func main() { definition := dynamicstruct.ExtendStruct(Data{}).Build()

mapWithStringKey := definition.NewMapOfStructs("")

data := []byte( { &quot;element&quot;: { &quot;int&quot;: 123, &quot;someText&quot;: &quot;example&quot;, &quot;double&quot;: 123.45, &quot;Boolean&quot;: true, &quot;Slice&quot;: [1, 2, 3], &quot;Anonymous&quot;: &quot;avoid to read&quot; } } )

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

🔗 More in this category

© 2026 GitRepoTrend · Ompluscator/dynamic-struct · Updated daily from GitHub