Extract struct fields
This commit is contained in:
parent
2d4702781b
commit
15133ced93
|
@ -6,13 +6,21 @@ import (
|
|||
)
|
||||
|
||||
type testConf struct {
|
||||
Foo string `json:"foo"`
|
||||
Bar int `json:"bar"`
|
||||
AppName string `json:"app_name"`
|
||||
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 (
|
||||
goodJSON = `{"foo": "baz", "bar": 1}`
|
||||
badJSON = `{"foo": "noooo...`
|
||||
goodJSON = `{"app_name": "Confection", "version": 1}`
|
||||
badJSON = `{"app_name": "noooo...`
|
||||
)
|
||||
|
||||
func TestIsStructPtr(t *testing.T) {
|
||||
|
@ -38,11 +46,11 @@ func TestUnmarshal(t *testing.T) {
|
|||
if err := json.Unmarshal([]byte(goodJSON), i); err != nil {
|
||||
t.Error("Unexpected error")
|
||||
}
|
||||
if conf.Foo != "baz" {
|
||||
t.Errorf("Expected Foo to equal %q, got %q", "baz", conf.Foo)
|
||||
if conf.AppName != "Confection" {
|
||||
t.Errorf("Expected Foo to equal %q, got %q", "Confection", conf.AppName)
|
||||
}
|
||||
if conf.Bar != 1 {
|
||||
t.Errorf("Expected Bar to equal %q, got %q", 1, conf.Bar)
|
||||
if conf.Version != 1 {
|
||||
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