https://github.com/goldeneggg/structil
Go struct utilities with reflection for JSON data decoding, map-liked data accessing, dynamic struct building and more
https://github.com/goldeneggg/structil
decoder go golang json json-parser structs
Last synced: 22 days ago
JSON representation
Go struct utilities with reflection for JSON data decoding, map-liked data accessing, dynamic struct building and more
- Host: GitHub
- URL: https://github.com/goldeneggg/structil
- Owner: goldeneggg
- License: mit
- Created: 2019-06-01T03:21:43.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-09-03T22:12:16.000Z (over 1 year ago)
- Last Synced: 2024-11-17T12:50:23.809Z (over 1 year ago)
- Topics: decoder, go, golang, json, json-parser, structs
- Language: Go
- Homepage:
- Size: 698 KB
- Stars: 50
- Watchers: 2
- Forks: 8
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
structil [](https://pkg.go.dev/github.com/goldeneggg/structil)
==========
[](https://github.com/goldeneggg/structil/actions)
[](https://goreportcard.com/report/github.com/goldeneggg/structil)
[](https://codecov.io/github/goldeneggg/structil?branch=master)
[](https://github.com/goldeneggg/structil/blob/master/LICENSE)
struct + util = __structil__, for runtime and dynamic environment in Go.
## Why?
I'd like to ...
- conveniently handle and decode the known or unknown formatted JSON/YAML
- conveniently dive into the specific field in nested struct
- simply verify if a field with the specified name and type exists in object
- etc
with Go reflection package experimentally.
```
*** JSON and YAML format is known or unknown ***
JSON →→→→→→→→→→→→→→→→↓ →→ (known format) struct →→→→→→→→→→→↓→→→ (use struct directly)
↓ ↑ ↓
↓→→ map →→→ (unknown format) "DynamicStruct" →→→→→→ "Getter", "Finder"
↑
YAML →→→→→→→→→→→→→→→→↑
↑
(and other formats) →↑
```
Please see [my medium post](https://medium.com/@s0k0mata/dynamic-and-runtime-struct-utilities-in-go-go-golang-reflection-25c154335185) as well.
## Sample Usecase
Try printing the struct definition from __the unknown formatted__ JSON decoding.
```go
package main
import (
"fmt"
"github.com/goldeneggg/structil/dynamicstruct/decoder"
)
func main() {
unknownJSON := []byte(`
{
"string_field":"かきくけこ",
"int_field":45678,
"bool_field":false,
"object_field":{
"id":12,
"name":"the name",
"nested_object_field": {
"address": "Tokyo",
"is_manager": true
}
},
"array_string_field":[
"array_str_1",
"array_str_2"
],
"array_struct_field":[
{
"kkk":"kkk1",
"vvvv":"vvv1"
},
{
"kkk":"kkk2",
"vvvv":"vvv2"
}
],
"null_field":null
}
`)
// create `Decoder` from JSON
dec, err := decoder.FromJSON(unknownJSON)
if err != nil {
panic(err)
}
// - If `nest` is true, nested object attributes will be also decoded to struct recursively
// - If `nest` is false, nested object attributes will be decoded to `map[string]interface{}`
nest := true
// - If `useTag` is true, JSON Struct tags are defined
useTag := true
// create `DynamicStruct` from `Decoder`
ds, err := dec.DynamicStruct(nest, useTag)
if err != nil {
panic(err)
}
// print struct definition from `DynamicStruct`
fmt.Println(ds.Definition())
}
```
This program will print a Go struct definition string as follows.
```go
// - Type name is "DynamicStruct" (raname is available)
// - Field names are automatically camelized from input json attribute names
// - Fields are ordered by field name
type DynamicStruct struct {
ArrayStringField []string `json:"array_string_field"`
ArrayStructField []struct {
Kkk string `json:"kkk"`
Vvvv string `json:"vvvv"`
} `json:"array_struct_field"`
BoolField bool `json:"bool_field"`
IntField float64 `json:"int_field"`
NullField interface {} `json:"null_field"`
ObjectField struct {
Id float64 `json:"id"`
Name string `json:"name"`
NestedObjectField struct {
Address string `json:"address"`
IsManager bool `json:"is_manager"`
} `json:"nested_object_field"`
} `json:"object_field"`
StringField string `json:"string_field"`
}
```
And see [example code](/dynamicstruct/decoder/example_test.go#L9).
## More Examples
### From JSON to `Getter`
We can convert from __the unknown formatted__ JSON to `Getter` via `DynamicStruct` with `decoder.JSONToGetter` function.
See [example code](/dynamicstruct/decoder/example_test.go#L76).
#### What is `Getter`?
We can access a struct using field name string, like (typed) map with `structil.NewGetter` function.
```go
g, err := structil.NewGetter(structOrStructPointerVariable)
// get num of struct fields
g.NumField()
// names of struct fields
g.Names()
// return true if struct has a "fName" field
g.Has(fName)
// get "fName" field value of the original struct as string
g.String(fName)
// return true if "fName" field value of the original struct is float64
g.IsFloat64(fName)
// convert from struct to map[string]interface{}
g.ToMap()
// get as `Getter` if "fName" field is a (nested) struct
gNest, ok := g.GetGetter(fName)
gNest.NumField()
gNest.Names()
```
See [example code](/example_test.go#L7)
##### `Getter.MapGet` method
`Getter.MapGet` method provides the __Map__ collection function for slice of struct
See [example code](/example_test.go#L56)
### From JSON to `DynamicStruct`
We can convert from __the unknown formatted__ JSON to `DynamicStruct` with `Decoder` (from `decoder.FromJSON` function) and `Decoder.DynamicStruct` method.
See [example code](/dynamicstruct/decoder/example_test.go#L9).
#### What is `DynamicStruct`?
We can create the dynamic and runtime struct.
See [example code](/dynamicstruct/example_test.go#L10)
### `Finder`
We can access usefully nested struct fields using field name string.
See [example code](/example_test.go#L115)
#### With config file? use `FinderKeys`
We can create a Finder from the configuration file that have some finding target keys. We support some file formats of configuration file such as `yaml`, `json`, `toml` and more.
See [example code](/example_test.go#L189)
___Thanks for the awesome configuration management library [spf13/viper](https://github.com/spf13/viper).___
## Benchmark
See [this file](https://github.com/goldeneggg/structil/blob/bench-latest/BENCHMARK_LATEST.txt)
It's the latest benchmark result that is executed on GitHub Actions runner instance.