Skip to content

Instantly share code, notes, and snippets.

@mjarkk
Created May 17, 2019 05:45
Show Gist options
  • Save mjarkk/0e1d3f1a1729dd9f1eb34cde0bd5d3db to your computer and use it in GitHub Desktop.
Save mjarkk/0e1d3f1a1729dd9f1eb34cde0bd5d3db to your computer and use it in GitHub Desktop.
Confert a golang struct into usable type data
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Test2 struct {
B string
}
type Test1 struct {
A string `json:"A-test-A"`
AA []string
Aa int
Ab int8
Ac int16
Ad int32
Ae int64
Af uint
Ag uint8
Ah uint16
Ai uint32
Aj uint64
Ak bool
Al *bool
C [][][]Test2
D struct {
A int
}
E map[string]string
F Test2
}
func main() {
out, err := GetTypeMap(Test1{}, true)
if err != nil {
panic(err)
}
b, err := json.Marshal(out)
if err != nil {
panic(err)
}
fmt.Println(string(b))
}
// GetTypeMap returns a map with the outline of a struct
func GetTypeMap(val interface{}, useJSONTags bool) (map[string]TypeField, error) {
v := reflect.ValueOf(val)
if v.Kind() == reflect.Struct {
return parseStruct(v.Type(), useJSONTags), nil
}
return map[string]TypeField{}, fmt.Errorf("val must be a struct")
}
// TypeField describes a struct's value
type TypeField struct {
Type string `json:"type"`
NestedOptions []string `json:"nestedOptions"`
StructDetials map[string]TypeField `json:"structDetials"`
}
func parseStruct(t reflect.Type, useJSONTags bool) map[string]TypeField {
toReturn := map[string]TypeField{}
for i := 0; i < t.NumField(); i++ {
name := t.Field(i).Name
jsonName := t.Field(i).Tag.Get("json")
if useJSONTags && jsonName != "" {
name = jsonName
}
ft := t.Field(i).Type
kind := ft.Kind()
toAdd := TypeField{}
// Deal with the pointers, maps, arrays
looper:
for {
switch kind {
case reflect.Slice:
toAdd.NestedOptions = append(toAdd.NestedOptions, "slice")
ft = ft.Elem()
kind = ft.Kind()
case reflect.Map:
toAdd.NestedOptions = append(toAdd.NestedOptions, ft.Key().Name())
ft = ft.Elem()
kind = ft.Kind()
case reflect.Ptr:
toAdd.NestedOptions = append(toAdd.NestedOptions, "ptr")
ft = ft.Elem()
kind = ft.Kind()
default:
break looper
}
}
switch kind {
case reflect.Struct:
toAdd.Type = kind.String()
toAdd.StructDetials = parseStruct(ft, useJSONTags)
case reflect.Bool, reflect.String, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
toAdd.Type = kind.String()
default:
fmt.Println(name+", Unkown kind:", ft.String(), ft.Kind())
continue
}
toReturn[name] = toAdd
}
return toReturn
}
{
"A-test-A": {
"type": "string",
"nestedOptions": null,
"structDetials": null
},
"AA": {
"type": "string",
"nestedOptions": [
"slice"
],
"structDetials": null
},
"Aa": {
"type": "int",
"nestedOptions": null,
"structDetials": null
},
"Ab": {
"type": "int8",
"nestedOptions": null,
"structDetials": null
},
"Ac": {
"type": "int16",
"nestedOptions": null,
"structDetials": null
},
"Ad": {
"type": "int32",
"nestedOptions": null,
"structDetials": null
},
"Ae": {
"type": "int64",
"nestedOptions": null,
"structDetials": null
},
"Af": {
"type": "uint",
"nestedOptions": null,
"structDetials": null
},
"Ag": {
"type": "uint8",
"nestedOptions": null,
"structDetials": null
},
"Ah": {
"type": "uint16",
"nestedOptions": null,
"structDetials": null
},
"Ai": {
"type": "uint32",
"nestedOptions": null,
"structDetials": null
},
"Aj": {
"type": "uint64",
"nestedOptions": null,
"structDetials": null
},
"Ak": {
"type": "bool",
"nestedOptions": null,
"structDetials": null
},
"Al": {
"type": "bool",
"nestedOptions": [
"ptr"
],
"structDetials": null
},
"C": {
"type": "struct",
"nestedOptions": [
"slice",
"slice",
"slice"
],
"structDetials": {
"B": {
"type": "string",
"nestedOptions": null,
"structDetials": null
}
}
},
"D": {
"type": "struct",
"nestedOptions": null,
"structDetials": {
"A": {
"type": "int",
"nestedOptions": null,
"structDetials": null
}
}
},
"E": {
"type": "string",
"nestedOptions": [
"string"
],
"structDetials": null
},
"F": {
"type": "struct",
"nestedOptions": null,
"structDetials": {
"B": {
"type": "string",
"nestedOptions": null,
"structDetials": null
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment