Commit b8b73a35 authored by earncef's avatar earncef Committed by Hanzei
Browse files

URLQuery with index slice keys (#74)

* URLQuery with index slice keys

* Added tests

* Cleanup

* Added test for MSI and cleaned up redundant code

* Added SetURLValuesSliceKeySuffix()

* Added error to SetURLValuesSliceKeySuffix()
parent 9e1dfc12
......@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"net/url"
"strconv"
)
// SignatureSeparator is the character that is used to
......@@ -14,9 +15,34 @@ const SignatureSeparator = "_"
// URLValuesSliceKeySuffix is the character that is used to
// specify a suffic for slices parsed by URLValues.
// If the suffix is set to "[i]", then the index of the slice
// is used in place of i
// Ex: Suffix "[]" would have the form a[]=b&a[]=c
// OR Suffix "[i]" would have the form a[0]=b&a[1]=c
// OR Suffix "" would have the form a=b&a=c
var URLValuesSliceKeySuffix = "[]"
var urlValuesSliceKeySuffix = "[]"
const (
URLValuesSliceKeySuffixEmpty = ""
URLValuesSliceKeySuffixArray = "[]"
URLValuesSliceKeySuffixIndex = "[i]"
)
// SetURLValuesSliceKeySuffix sets the character that is used to
// specify a suffic for slices parsed by URLValues.
// If the suffix is set to "[i]", then the index of the slice
// is used in place of i
// Ex: Suffix "[]" would have the form a[]=b&a[]=c
// OR Suffix "[i]" would have the form a[0]=b&a[1]=c
// OR Suffix "" would have the form a=b&a=c
func SetURLValuesSliceKeySuffix(s string) error {
if s == URLValuesSliceKeySuffixEmpty || s == URLValuesSliceKeySuffixArray || s == URLValuesSliceKeySuffixIndex {
urlValuesSliceKeySuffix = s
return nil
}
return errors.New("objx: Invalid URLValuesSliceKeySuffix provided.")
}
// JSON converts the contained object to a JSON string
// representation
......@@ -106,50 +132,74 @@ func (m Map) URLValues() url.Values {
}
func (m Map) parseURLValues(queryMap Map, vals url.Values, key string) {
useSliceIndex := false
if urlValuesSliceKeySuffix == "[i]" {
useSliceIndex = true
}
for k, v := range queryMap {
val := &Value{data: v}
switch {
case val.IsObjxMap():
if key == "" {
m.parseURLValues(v.(Map), vals, k)
m.parseURLValues(val.ObjxMap(), vals, k)
} else {
m.parseURLValues(v.(Map), vals, key+"["+k+"]")
m.parseURLValues(val.ObjxMap(), vals, key+"["+k+"]")
}
case val.IsObjxMapSlice():
sliceKey := k + URLValuesSliceKeySuffix
sliceKey := k
if key != "" {
sliceKey = key + "[" + k + "]" + URLValuesSliceKeySuffix
sliceKey = key + "[" + k + "]"
}
for _, sv := range val.MustObjxMapSlice() {
m.parseURLValues(sv, vals, sliceKey)
}
case val.IsMSI():
if key == "" {
m.parseURLValues(New(v), vals, k)
if useSliceIndex {
for i, sv := range val.MustObjxMapSlice() {
sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
m.parseURLValues(sv, vals, sk)
}
} else {
m.parseURLValues(New(v), vals, key+"["+k+"]")
sliceKey = sliceKey + urlValuesSliceKeySuffix
for _, sv := range val.MustObjxMapSlice() {
m.parseURLValues(sv, vals, sliceKey)
}
}
case val.IsMSISlice():
sliceKey := k + URLValuesSliceKeySuffix
sliceKey := k
if key != "" {
sliceKey = key + "[" + k + "]" + URLValuesSliceKeySuffix
sliceKey = key + "[" + k + "]"
}
for _, sv := range val.MustMSISlice() {
m.parseURLValues(New(sv), vals, sliceKey)
if useSliceIndex {
for i, sv := range val.MustMSISlice() {
sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
m.parseURLValues(New(sv), vals, sk)
}
} else {
sliceKey = sliceKey + urlValuesSliceKeySuffix
for _, sv := range val.MustMSISlice() {
m.parseURLValues(New(sv), vals, sliceKey)
}
}
case val.IsStrSlice(), val.IsBoolSlice(),
val.IsFloat32Slice(), val.IsFloat64Slice(),
val.IsIntSlice(), val.IsInt8Slice(), val.IsInt16Slice(), val.IsInt32Slice(), val.IsInt64Slice(),
val.IsUintSlice(), val.IsUint8Slice(), val.IsUint16Slice(), val.IsUint32Slice(), val.IsUint64Slice():
sliceKey := k + URLValuesSliceKeySuffix
sliceKey := k
if key != "" {
sliceKey = key + "[" + k + "]" + URLValuesSliceKeySuffix
sliceKey = key + "[" + k + "]"
}
if useSliceIndex {
for i, sv := range val.StringSlice() {
sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
vals.Set(sk, sv)
}
} else {
sliceKey = sliceKey + urlValuesSliceKeySuffix
vals[sliceKey] = val.StringSlice()
}
vals[sliceKey] = val.StringSlice()
default:
if key == "" {
vals.Set(k, val.String())
......
......@@ -93,6 +93,11 @@ func TestConversionURLValues(t *testing.T) {
"bools[]": []string{"true", "false"},
"mapSlice[][age]": []string{"40"},
"mapSlice[][height]": []string{"152"},
"msiData[age]": []string{"30"},
"msiData[height]": []string{"162"},
"msiData[arr][]": []string{"1", "2"},
"msiSlice[][age]": []string{"40"},
"msiSlice[][height]": []string{"152"},
}, u)
}
......@@ -107,12 +112,12 @@ func TestConversionURLQuery(t *testing.T) {
assert.Nil(t, err)
require.NotNil(t, ue)
assert.Equal(t, "abc=123&bools[]=true&bools[]=false&data[age]=30&data[arr][]=1&data[arr][]=2&data[height]=162&mapSlice[][age]=40&mapSlice[][height]=152&name=Mat&stats[]=1&stats[]=2", ue)
assert.Equal(t, "abc=123&bools[]=true&bools[]=false&data[age]=30&data[arr][]=1&data[arr][]=2&data[height]=162&mapSlice[][age]=40&mapSlice[][height]=152&msiData[age]=30&msiData[arr][]=1&msiData[arr][]=2&msiData[height]=162&msiSlice[][age]=40&msiSlice[][height]=152&name=Mat&stats[]=1&stats[]=2", ue)
}
func TestConversionURLQueryNoSliceKeySuffix(t *testing.T) {
m := getURLQueryMap()
objx.URLValuesSliceKeySuffix = ""
objx.SetURLValuesSliceKeySuffix(objx.URLValuesSliceKeySuffixEmpty)
u, err := m.URLQuery()
assert.Nil(t, err)
......@@ -122,7 +127,34 @@ func TestConversionURLQueryNoSliceKeySuffix(t *testing.T) {
assert.Nil(t, err)
require.NotNil(t, ue)
assert.Equal(t, "abc=123&bools=true&bools=false&data[age]=30&data[arr]=1&data[arr]=2&data[height]=162&mapSlice[age]=40&mapSlice[height]=152&name=Mat&stats=1&stats=2", ue)
assert.Equal(t, "abc=123&bools=true&bools=false&data[age]=30&data[arr]=1&data[arr]=2&data[height]=162&mapSlice[age]=40&mapSlice[height]=152&msiData[age]=30&msiData[arr]=1&msiData[arr]=2&msiData[height]=162&msiSlice[age]=40&msiSlice[height]=152&name=Mat&stats=1&stats=2", ue)
}
func TestConversionURLQueryIndexSliceKeySuffix(t *testing.T) {
m := getURLQueryMap()
m.Set("mapSlice", []objx.Map{{"age": 40, "sex": "male"}, {"height": 152}})
objx.SetURLValuesSliceKeySuffix(objx.URLValuesSliceKeySuffixIndex)
u, err := m.URLQuery()
assert.Nil(t, err)
require.NotNil(t, u)
ue, err := url.QueryUnescape(u)
assert.Nil(t, err)
require.NotNil(t, ue)
assert.Equal(t, "abc=123&bools[0]=true&bools[1]=false&data[age]=30&data[arr][0]=1&data[arr][1]=2&data[height]=162&mapSlice[0][age]=40&mapSlice[0][sex]=male&mapSlice[1][height]=152&msiData[age]=30&msiData[arr][0]=1&msiData[arr][1]=2&msiData[height]=162&msiSlice[0][age]=40&msiSlice[1][height]=152&name=Mat&stats[0]=1&stats[1]=2", ue)
}
func TestValidityURLQuerySliceKeySuffix(t *testing.T) {
err := objx.SetURLValuesSliceKeySuffix("")
assert.Nil(t, err)
err = objx.SetURLValuesSliceKeySuffix("[]")
assert.Nil(t, err)
err = objx.SetURLValuesSliceKeySuffix("[i]")
assert.Nil(t, err)
err = objx.SetURLValuesSliceKeySuffix("{}")
assert.Error(t, err)
}
func getURLQueryMap() objx.Map {
......@@ -131,6 +163,8 @@ func getURLQueryMap() objx.Map {
"name": "Mat",
"data": objx.Map{"age": 30, "height": 162, "arr": []int{1, 2}},
"mapSlice": []objx.Map{{"age": 40}, {"height": 152}},
"msiData": map[string]interface{}{"age": 30, "height": 162, "arr": []int{1, 2}},
"msiSlice": []map[string]interface{}{{"age": 40}, {"height": 152}},
"stats": []string{"1", "2"},
"bools": []bool{true, false},
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment