forked from mirror/cast
Add support for maps defined as a json string
This commit is contained in:
parent
acbeb36b90
commit
9ebc15c905
22
cast_test.go
22
cast_test.go
|
@ -697,6 +697,10 @@ func TestStringMapStringSliceE(t *testing.T) {
|
||||||
var stringMapInterface1 = map[string]interface{}{"key 1": []string{"value 1"}, "key 2": []string{"value 2"}}
|
var stringMapInterface1 = map[string]interface{}{"key 1": []string{"value 1"}, "key 2": []string{"value 2"}}
|
||||||
var stringMapInterfaceResult1 = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2"}}
|
var stringMapInterfaceResult1 = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2"}}
|
||||||
|
|
||||||
|
var jsonStringMapString = `{"key 1": "value 1", "key 2": "value 2"}`
|
||||||
|
var jsonStringMapStringArray = `{"key 1": ["value 1"], "key 2": ["value 2", "value 3"]}`
|
||||||
|
var jsonStringMapStringArrayResult = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2", "value 3"}}
|
||||||
|
|
||||||
type Key struct {
|
type Key struct {
|
||||||
k string
|
k string
|
||||||
}
|
}
|
||||||
|
@ -718,11 +722,15 @@ func TestStringMapStringSliceE(t *testing.T) {
|
||||||
{interfaceMapInterfaceSlice, stringMapStringSlice, false},
|
{interfaceMapInterfaceSlice, stringMapStringSlice, false},
|
||||||
{interfaceMapString, stringMapStringSingleSliceFieldsResult, false},
|
{interfaceMapString, stringMapStringSingleSliceFieldsResult, false},
|
||||||
{interfaceMapInterface, stringMapStringSingleSliceFieldsResult, false},
|
{interfaceMapInterface, stringMapStringSingleSliceFieldsResult, false},
|
||||||
|
{jsonStringMapStringArray, jsonStringMapStringArrayResult, false},
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
{nil, nil, true},
|
{nil, nil, true},
|
||||||
{testing.T{}, nil, true},
|
{testing.T{}, nil, true},
|
||||||
{map[interface{}]interface{}{"foo": testing.T{}}, nil, true},
|
{map[interface{}]interface{}{"foo": testing.T{}}, nil, true},
|
||||||
{map[interface{}]interface{}{Key{"foo"}: "bar"}, nil, true}, // ToStringE(Key{"foo"}) should fail
|
{map[interface{}]interface{}{Key{"foo"}: "bar"}, nil, true}, // ToStringE(Key{"foo"}) should fail
|
||||||
|
{jsonStringMapString, nil, true},
|
||||||
|
{"", nil, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -751,9 +759,13 @@ func TestToStringMapE(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{map[interface{}]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
|
{map[interface{}]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
|
||||||
{map[string]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
|
{map[string]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
|
||||||
|
{`{"tag": "tags", "group": "groups"}`, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
|
||||||
|
{`{"tag": "tags", "group": true}`, map[string]interface{}{"tag": "tags", "group": true}, false},
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
{nil, nil, true},
|
{nil, nil, true},
|
||||||
{testing.T{}, nil, true},
|
{testing.T{}, nil, true},
|
||||||
|
{"", nil, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -783,9 +795,12 @@ func TestToStringMapBoolE(t *testing.T) {
|
||||||
{map[interface{}]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
|
{map[interface{}]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
|
||||||
{map[string]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
|
{map[string]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
|
||||||
{map[string]bool{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
|
{map[string]bool{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
|
||||||
|
{`{"v1": true, "v2": false}`, map[string]bool{"v1": true, "v2": false}, false},
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
{nil, nil, true},
|
{nil, nil, true},
|
||||||
{testing.T{}, nil, true},
|
{testing.T{}, nil, true},
|
||||||
|
{"", nil, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -811,6 +826,9 @@ func TestToStringMapStringE(t *testing.T) {
|
||||||
var stringMapInterface = map[string]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
|
var stringMapInterface = map[string]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
|
||||||
var interfaceMapString = map[interface{}]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
|
var interfaceMapString = map[interface{}]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
|
||||||
var interfaceMapInterface = map[interface{}]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
|
var interfaceMapInterface = map[interface{}]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
|
||||||
|
var jsonString = `{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}`
|
||||||
|
var invalidJsonString = `{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"`
|
||||||
|
var emptyString = ""
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input interface{}
|
input interface{}
|
||||||
|
@ -821,9 +839,13 @@ func TestToStringMapStringE(t *testing.T) {
|
||||||
{stringMapInterface, stringMapString, false},
|
{stringMapInterface, stringMapString, false},
|
||||||
{interfaceMapString, stringMapString, false},
|
{interfaceMapString, stringMapString, false},
|
||||||
{interfaceMapInterface, stringMapString, false},
|
{interfaceMapInterface, stringMapString, false},
|
||||||
|
{jsonString, stringMapString, false},
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
{nil, nil, true},
|
{nil, nil, true},
|
||||||
{testing.T{}, nil, true},
|
{testing.T{}, nil, true},
|
||||||
|
{invalidJsonString, nil, true},
|
||||||
|
{emptyString, nil, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
|
20
caste.go
20
caste.go
|
@ -6,6 +6,7 @@
|
||||||
package cast
|
package cast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
@ -872,6 +873,9 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
|
||||||
m[ToString(k)] = ToString(val)
|
m[ToString(k)] = ToString(val)
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
case string:
|
||||||
|
err := jsonStringToObject(v, &m)
|
||||||
|
return m, err
|
||||||
default:
|
default:
|
||||||
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i)
|
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i)
|
||||||
}
|
}
|
||||||
|
@ -932,6 +936,9 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
|
||||||
}
|
}
|
||||||
m[key] = value
|
m[key] = value
|
||||||
}
|
}
|
||||||
|
case string:
|
||||||
|
err := jsonStringToObject(v, &m)
|
||||||
|
return m, err
|
||||||
default:
|
default:
|
||||||
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
|
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
|
||||||
}
|
}
|
||||||
|
@ -955,6 +962,9 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
|
||||||
return m, nil
|
return m, nil
|
||||||
case map[string]bool:
|
case map[string]bool:
|
||||||
return v, nil
|
return v, nil
|
||||||
|
case string:
|
||||||
|
err := jsonStringToObject(v, &m)
|
||||||
|
return m, err
|
||||||
default:
|
default:
|
||||||
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i)
|
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i)
|
||||||
}
|
}
|
||||||
|
@ -972,6 +982,9 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
|
||||||
return m, nil
|
return m, nil
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
return v, nil
|
return v, nil
|
||||||
|
case string:
|
||||||
|
err := jsonStringToObject(v, &m)
|
||||||
|
return m, err
|
||||||
default:
|
default:
|
||||||
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i)
|
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i)
|
||||||
}
|
}
|
||||||
|
@ -1144,3 +1157,10 @@ func parseDateWith(s string, dates []string) (d time.Time, e error) {
|
||||||
}
|
}
|
||||||
return d, fmt.Errorf("unable to parse date: %s", s)
|
return d, fmt.Errorf("unable to parse date: %s", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// jsonStringToObject attempts to unmarshall a string as JSON into
|
||||||
|
// the object passed as pointer.
|
||||||
|
func jsonStringToObject(s string, v interface{}) error {
|
||||||
|
data := []byte(s)
|
||||||
|
return json.Unmarshal(data, v)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue