Extract struct fields
This commit is contained in:
parent
2d4702781b
commit
15133ced93
|
@ -6,13 +6,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type testConf struct {
|
type testConf struct {
|
||||||
Foo string `json:"foo"`
|
AppName string `json:"app_name"`
|
||||||
Bar int `json:"bar"`
|
Version float32 `json:"version"`
|
||||||
|
Database testDatabaseConf `json:"database"`
|
||||||
|
}
|
||||||
|
type testDatabaseConf struct {
|
||||||
|
Adapter string `json:"adapter"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
goodJSON = `{"foo": "baz", "bar": 1}`
|
goodJSON = `{"app_name": "Confection", "version": 1}`
|
||||||
badJSON = `{"foo": "noooo...`
|
badJSON = `{"app_name": "noooo...`
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsStructPtr(t *testing.T) {
|
func TestIsStructPtr(t *testing.T) {
|
||||||
|
@ -38,11 +46,11 @@ func TestUnmarshal(t *testing.T) {
|
||||||
if err := json.Unmarshal([]byte(goodJSON), i); err != nil {
|
if err := json.Unmarshal([]byte(goodJSON), i); err != nil {
|
||||||
t.Error("Unexpected error")
|
t.Error("Unexpected error")
|
||||||
}
|
}
|
||||||
if conf.Foo != "baz" {
|
if conf.AppName != "Confection" {
|
||||||
t.Errorf("Expected Foo to equal %q, got %q", "baz", conf.Foo)
|
t.Errorf("Expected Foo to equal %q, got %q", "Confection", conf.AppName)
|
||||||
}
|
}
|
||||||
if conf.Bar != 1 {
|
if conf.Version != 1 {
|
||||||
t.Errorf("Expected Bar to equal %q, got %q", 1, conf.Bar)
|
t.Errorf("Expected Bar to equal %q, got %q", 1, conf.Version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package confection2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type field struct {
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
Val interface{} `json:"val"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractFields(st interface{}, path string) map[string]field {
|
||||||
|
res := make(map[string]field)
|
||||||
|
typ := reflect.TypeOf(st)
|
||||||
|
val := reflect.ValueOf(st)
|
||||||
|
for i := 0; i < val.NumField(); i++ {
|
||||||
|
ftyp := typ.Field(i)
|
||||||
|
fval := val.Field(i)
|
||||||
|
|
||||||
|
switch kind := fval.Kind(); kind {
|
||||||
|
case reflect.Struct:
|
||||||
|
sub := extractFields(fval.Interface(), ftyp.Name+".")
|
||||||
|
for k, v := range sub {
|
||||||
|
res[k] = v
|
||||||
|
}
|
||||||
|
case reflect.Bool,
|
||||||
|
reflect.Int,
|
||||||
|
reflect.Int8,
|
||||||
|
reflect.Int16,
|
||||||
|
reflect.Int32,
|
||||||
|
reflect.Int64,
|
||||||
|
reflect.Uint,
|
||||||
|
reflect.Uint8,
|
||||||
|
reflect.Uint16,
|
||||||
|
reflect.Uint32,
|
||||||
|
reflect.Uint64,
|
||||||
|
reflect.Float32,
|
||||||
|
reflect.Float64,
|
||||||
|
reflect.String:
|
||||||
|
res[path+ftyp.Name] = field{
|
||||||
|
Kind: kind.String(),
|
||||||
|
Val: fval.Interface(),
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Printf("Field type %q not supported for field %q\n", kind, path+ftyp.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package confection2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExtractFields(t *testing.T) {
|
||||||
|
c := testConf{
|
||||||
|
AppName: "Confection",
|
||||||
|
Version: 1.1,
|
||||||
|
Database: testDatabaseConf{
|
||||||
|
Adapter: "mysql",
|
||||||
|
Host: "localhost",
|
||||||
|
Port: 3306,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := extractFields(c, "")
|
||||||
|
testField := func(fieldName, kind string, val interface{}) {
|
||||||
|
if f, ok := fields[fieldName]; ok {
|
||||||
|
if f.Kind != kind {
|
||||||
|
t.Errorf("%s expected to be of kind %q, got %q", fieldName, kind, f.Kind)
|
||||||
|
}
|
||||||
|
if f.Val != val {
|
||||||
|
t.Errorf("%s expected to have value %q, got %q", fieldName, val, f.Val)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Missing %s field", fieldName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testField("AppName", "string", c.AppName)
|
||||||
|
testField("Version", "float32", c.Version)
|
||||||
|
testField("Database.Adapter", "string", c.Database.Adapter)
|
||||||
|
testField("Database.Host", "string", c.Database.Host)
|
||||||
|
testField("Database.Port", "int", c.Database.Port)
|
||||||
|
}
|
Loading…
Reference in New Issue