diff --git a/confection_test.go b/confection_test.go index e4b269d..3ff61a9 100644 --- a/confection_test.go +++ b/confection_test.go @@ -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) } } diff --git a/field.go b/field.go new file mode 100644 index 0000000..ff0fe4d --- /dev/null +++ b/field.go @@ -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 +} diff --git a/field_test.go b/field_test.go new file mode 100644 index 0000000..916d0ab --- /dev/null +++ b/field_test.go @@ -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) +}