Skip to content

Commit

Permalink
feat(SPV-793): handle arrays in query string
Browse files Browse the repository at this point in the history
  • Loading branch information
dorzepowski committed Aug 23, 2024
1 parent 0dafdae commit 60af61a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 7 deletions.
14 changes: 14 additions & 0 deletions internal/query/gin_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ func TestContextQueryNestedMap(t *testing.T) {
},
exists: true,
},
"handle explicit arrays accessors ([]) at the value level": {
url: "?mapkey[key][]=value1&mapkey[key][]=value2",
expectedResult: map[string]interface{}{
"key": []string{"value1", "value2"},
},
exists: true,
},
"implicit arrays (duplicated key) at the value level will return only first value": {
url: "?mapkey[key]=value1&mapkey[key]=value2",
expectedResult: map[string]interface{}{
"key": "value1",
},
exists: true,
},
}
for name, test := range tests {
t.Run("getQueryMap: "+name, func(t *testing.T) {
Expand Down
19 changes: 13 additions & 6 deletions internal/query/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,9 @@ func isKey(k string, key string) bool {
// For example, key[foo][bar] will be parsed to ["foo", "bar"].
func parsePath(k string, key string) ([]string, error) {
rawPath := strings.TrimPrefix(k, key)
if rawPath == "" {
return nil, fmt.Errorf("expect %s to be a map but got value", key)
}
splitted := strings.Split(rawPath, "]")
paths := make([]string, 0)
for _, p := range splitted {
for i, p := range splitted {
if p == "" {
continue
}
Expand All @@ -49,7 +46,7 @@ func parsePath(k string, key string) ([]string, error) {
} else {
return nil, fmt.Errorf("invalid access to map key %s", p)
}
if p == "" {
if i == 0 && p == "" {
return nil, fmt.Errorf("expect %s to be a map but got array", key)
}
paths = append(paths, p)
Expand All @@ -60,17 +57,27 @@ func parsePath(k string, key string) ([]string, error) {
// setValueOnPath is an internal function to set value a path on dicts.
func setValueOnPath(dicts map[string]interface{}, paths []string, value []string) {
nesting := len(paths)
previousLevel := dicts
currentLevel := dicts
for i, p := range paths {
if isLast(i, nesting) {
currentLevel[p] = value[0]
if isArray(p) {
previousLevel[paths[i-1]] = value
} else {
currentLevel[p] = value[0]
}
} else {
initNestingIfNotExists(currentLevel, p)
previousLevel = currentLevel
currentLevel = currentLevel[p].(map[string]interface{})
}
}
}

func isArray(p string) bool {
return p == ""
}

// initNestingIfNotExists is an internal function to initialize a nested map if not exists.
func initNestingIfNotExists(currentLevel map[string]interface{}, p string) {
if _, ok := currentLevel[p]; !ok {
Expand Down
3 changes: 2 additions & 1 deletion models/filter/access_key_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ type AccessKeyFilter struct {
ModelFilter `json:",inline"`

// RevokedRange specifies the time range when a record was revoked.
RevokedRange *TimeRange `json:"revokedRange,omitempty"`
RevokedRange *TimeRange `form:"revokedRange" json:"revokedRange,omitempty"`
Test bool `form:"test" json:"test,omitempty"`
}

// ToDbConditions converts filter fields to the datastore conditions using gorm naming strategy
Expand Down

0 comments on commit 60af61a

Please sign in to comment.