Refactor Decode(map[string]interface{})
diff --git a/decode.go b/decode.go
index 7364ccc..de540f4 100644
--- a/decode.go
+++ b/decode.go
@@ -8,12 +8,16 @@
 	"time"
 )
 
-// Decode assigns property values to exported fields of a struct.
+// Decode assigns property values to exported fields of a struct or a
+// map[string]interface{}.
 //
-// Decode traverses v recursively and returns an error if a value cannot be
+// Decode traverses x recursively and returns an error if a value cannot be
 // converted to the field type or a required value is missing for a field.
+// If x is a map[string]interface{} the keys are traversed using dot notation.
+// Values which contain semicolons are decoded as []string and all other
+// values are decoded as string values.
 //
-// The following type dependent decodings are used:
+// For structs the following type dependent decodings are used:
 //
 // String, boolean, numeric fields have the value of the property key assigned.
 // The property key name is the name of the field. A different key and a default
@@ -89,52 +93,50 @@
 //     Field map[string]string `properties:"myName"`
 func (p *Properties) Decode(x interface{}) error {
 	t, v := reflect.TypeOf(x), reflect.ValueOf(x)
+	elemT := v.Elem().Type()
 
-	if isPtr(t) {
-		elemT := v.Elem().Type()
-		switch {
-		case isMap(elemT):
-			m, ok := x.(*map[string]interface{})
-			if !ok {
-				return fmt.Errorf("map type not map[string]interface {}", elemT)
-			}
-			for _, key := range p.Keys() {
-				value, _ := p.Get(key)
-				setNestedKey(*m, key, value)
-			}
-			return nil
-
-		case isStruct(elemT):
-			if err := dec(p, "", nil, nil, v); err != nil {
-				return err
-			}
-			return nil
+	switch {
+	case isPtr(t) && isMap(elemT):
+		m, ok := x.(*map[string]interface{})
+		if !ok {
+			return fmt.Errorf("not a map[string]interface{}: %s", elemT)
 		}
-	}
-
-	return fmt.Errorf("not a pointer to map or struct: %s", t)
-}
-
-func setNestedKey(m map[string]interface{}, key string, value interface{}) {
-	if strings.Contains(key, ".") {
-		kk := strings.SplitN(key, ".", 2)
-		prefix, rest := kk[0], kk[1]
-		if _, ok := m[prefix]; !ok {
-			m[prefix] = map[string]interface{}{}
+		for key, val := range p.m {
+			decMap(*m, key, val)
 		}
-		setNestedKey(m[prefix].(map[string]interface{}), rest, value)
-	} else {
-		if reflect.TypeOf(value).Kind() == reflect.String {
-			val := value.(string)
-			if strings.Contains(val, ";") {
-				value = split(val, ";")
-			}
+		return nil
+
+	case isPtr(t) && isStruct(elemT):
+		if err := decStruct(p, "", nil, nil, v); err != nil {
+			return err
 		}
-		m[key] = value
+		return nil
+
+	default:
+		return fmt.Errorf("not a pointer to map or struct: %s", t)
 	}
 }
 
-func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error {
+func decMap(m map[string]interface{}, key, val string) {
+	if !strings.Contains(key, ".") {
+		// TODO(cp): why support arrays and why semicolons instead of comma like decStruct?
+		if strings.Contains(val, ";") {
+			m[key] = split(val, ";")
+		} else {
+			m[key] = val
+		}
+		return
+	}
+
+	kk := strings.SplitN(key, ".", 2)
+	prefix, rest := kk[0], kk[1]
+	if _, ok := m[prefix]; !ok {
+		m[prefix] = map[string]interface{}{}
+	}
+	decMap(m[prefix].(map[string]interface{}), rest, val)
+}
+
+func decStruct(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error {
 	t := v.Type()
 
 	// value returns the property value for key or the default if provided.
@@ -215,7 +217,7 @@
 		v.Set(val)
 
 	case isPtr(t):
-		return dec(p, key, def, opts, v.Elem())
+		return decStruct(p, key, def, opts, v.Elem())
 
 	case isStruct(t):
 		for i := 0; i < v.NumField(); i++ {
@@ -230,7 +232,7 @@
 			if key != "" {
 				fk = key + "." + fk
 			}
-			if err := dec(p, fk, def, opts, fv); err != nil {
+			if err := decStruct(p, fk, def, opts, fv); err != nil {
 				return err
 			}
 		}
@@ -258,7 +260,7 @@
 		for postfix, _ := range p.FilterStripPrefix(key + ".").m {
 			pp := strings.SplitN(postfix, ".", 2)
 			mk, mv := pp[0], reflect.New(valT)
-			if err := dec(p, key+"."+mk, nil, nil, mv); err != nil {
+			if err := decStruct(p, key+"."+mk, nil, nil, mv); err != nil {
 				return err
 			}
 			m.SetMapIndex(reflect.ValueOf(mk), mv.Elem())
diff --git a/decode_test.go b/decode_test.go
index bd74f3b..108bf1e 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -273,7 +273,7 @@
 	testDecode(t, in, &X{}, out)
 }
 
-func TestDecodeToStringMap(t *testing.T) {
+func TestDecodeStringMap(t *testing.T) {
 	type S struct {
 		A string
 	}