1
0
Fork 0

Extract struct fields

This commit is contained in:
Gregory Eremin 2015-08-29 15:25:47 +03:00
parent 2d4702781b
commit 15133ced93
3 changed files with 104 additions and 8 deletions

View File

@ -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)
}
}

51
field.go Normal file
View File

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

37
field_test.go Normal file
View File

@ -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)
}