Skip to content

Commit

Permalink
feat: support Set with slice/array index using square brackets. issue #…
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Aug 25, 2022
1 parent 752b6e9 commit df9cb3b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 62 deletions.
4 changes: 3 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ JSON format content example:
}
Usage please see example(more example please see examples folder in the lib):
*/
package config

Expand Down Expand Up @@ -206,6 +205,9 @@ func (c *Config) LoadedFiles() []string { return c.loadedFiles }
// DriverNames get loaded driver names
func (c *Config) DriverNames() []string { return c.driverNames }

// Reset data and caches
func Reset() { dc.ClearAll() }

// ClearAll data and caches
func ClearAll() { dc.ClearAll() }

Expand Down
15 changes: 15 additions & 0 deletions issues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,18 @@ func TestIssues_81(t *testing.T) {
is.NoErr(err)
is.Eq(wantTm, opt.IdleTime)
}

// https://github.com/gookit/config/issues/96
func TestIssues_96(t *testing.T) {
is := assert.New(t)
c := config.New("test")

err := c.Set("parent.child[0]", "Test1")
is.NoErr(err)
err = c.Set("parent.child[1]", "Test2")
is.NoErr(err)

dump.Println(c.Data())
is.NotEmpty(c.Data())
is.Eq([]string{"Test1", "Test2"}, c.Get("parent.child"))
}
67 changes: 7 additions & 60 deletions write.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ package config

import (
"errors"
"strconv"
"strings"

"github.com/gookit/goutil/arrutil"
"github.com/gookit/goutil/maputil"
"github.com/gookit/goutil/strutil"
"github.com/imdario/mergo"
)

// some common errors
var (
errReadonly = errors.New("the config instance in 'readonly' mode")
errKeyIsEmpty = errors.New("the config key is cannot be empty")
ErrReadonly = errors.New("the config instance in 'readonly' mode")
ErrKeyIsEmpty = errors.New("the config key is cannot be empty")
)

// SetData for override the Config.Data
Expand All @@ -38,15 +36,15 @@ func Set(key string, val interface{}, setByPath ...bool) error {
// Set a value by key string.
func (c *Config) Set(key string, val interface{}, setByPath ...bool) (err error) {
if c.opts.Readonly {
return errReadonly
return ErrReadonly
}

c.lock.Lock()
defer c.lock.Unlock()

sep := c.opts.Delimiter
if key = formatKey(key, string(sep)); key == "" {
return errKeyIsEmpty
return ErrKeyIsEmpty
}

defer c.fireHook(OnSetValue)
Expand All @@ -61,60 +59,9 @@ func (c *Config) Set(key string, val interface{}, setByPath ...bool) (err error)
return
}

// set by path
keys := strings.Split(key, string(sep))
topK := keys[0]
paths := keys[1:]

var ok bool
var item interface{}

// find top item data based on top key
if item, ok = c.data[topK]; !ok {
// not found, is new add
c.data[topK] = buildValueByPath(paths, val)
return
}

switch typeData := item.(type) {
case map[interface{}]interface{}: // from yaml.v2
dstItem := make(map[interface{}]interface{}, len(typeData))
for k, v := range typeData {
dstItem[strutil.QuietString(k)] = v
}

// create a new item for the topK
newItem := buildValueByPath1(paths, val)
// merge new item to old item
if err = mergo.Merge(&dstItem, newItem, mergo.WithOverride); err != nil {
return
}

c.data[topK] = dstItem
case map[string]interface{}: // from json,toml,yaml.v3
// enhanced: 'top.sub'=string, can set 'top.sub' to other type. eg: 'top.sub'=map
if err = maputil.SetByKeys(&typeData, paths, val); err != nil {
return
}

c.data[topK] = typeData
case []interface{}: // is list array
index, err := strconv.Atoi(keys[1])
if len(keys) == 2 && err == nil {
if index <= len(typeData) {
typeData[index] = val
}

c.data[topK] = typeData
} else {
err = errors.New("max allow 1 level for setting array value, current key: " + key)
return err
}
default:
// as a top key
c.data[key] = val
// err = errors.New("not supported value type, cannot setting value for the key: " + key)
}
return
return maputil.SetByKeys(&c.data, keys, val)
}

/**
Expand Down
10 changes: 9 additions & 1 deletion write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import (
)

func TestSetData(t *testing.T) {
defer func() {
Reset()
}()

c := Default()

err := c.LoadStrings(JSON, jsonStr)
Expand All @@ -32,6 +36,10 @@ func TestSetData(t *testing.T) {
}

func TestSet(t *testing.T) {
defer func() {
ClearAll()
}()

is := assert.New(t)
c := Default()

Expand Down Expand Up @@ -163,7 +171,7 @@ func TestSet(t *testing.T) {
is.Equal("", val)
}

is.NoError(Set("name.sub", []int{2}))
is.NoError(Set("name.sub", []int{2}, false))
ints := Ints("name.sub")
is.Equal([]int{2}, ints)

Expand Down

0 comments on commit df9cb3b

Please sign in to comment.