Skip to content

Commit

Permalink
fix: fix set error on input yaml.v2 like data
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Aug 9, 2022
1 parent d0e34e7 commit 6d5e8a6
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 61 deletions.
42 changes: 25 additions & 17 deletions write.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package config

import (
"errors"
"fmt"
"strconv"
"strings"

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

Expand Down Expand Up @@ -77,15 +78,13 @@ func (c *Config) Set(key string, val interface{}, setByPath ...bool) (err error)
case map[interface{}]interface{}: // from yaml.v2
dstItem := make(map[interface{}]interface{}, len(typeData))
for k, v := range typeData {
sk := fmt.Sprintf("%v", k)
dstItem[sk] = v
dstItem[strutil.QuietString(k)] = v
}

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

Expand All @@ -94,13 +93,12 @@ func (c *Config) Set(key string, val interface{}, setByPath ...bool) (err error)
// create a new item for the topK
newItem := buildValueByPath(paths, val)
// merge new item to old item
err = mergo.Merge(&typeData, &newItem, mergo.WithOverride)
if err != nil {
if err = mergo.Merge(&typeData, &newItem, mergo.WithOverride); err != nil {
return
}

c.data[topK] = typeData
case []interface{}: // is array
case []interface{}: // is list array
index, err := strconv.Atoi(keys[1])
if len(keys) == 2 && err == nil {
if index <= len(typeData) {
Expand Down Expand Up @@ -131,7 +129,7 @@ func buildValueByPath(paths []string, val interface{}) (newItem map[string]inter
return map[string]interface{}{paths[0]: val}
}

sliceReverse(paths)
arrutil.Reverse(paths)

// multi nodes
for _, p := range paths {
Expand All @@ -144,12 +142,22 @@ func buildValueByPath(paths []string, val interface{}) (newItem map[string]inter
return
}

// reverse a slice. (slice 是引用,所以可以直接改变)
func sliceReverse(ss []string) {
ln := len(ss)
for i := 0; i < ln/2; i++ {
li := ln - i - 1
// fmt.Println(i, "<=>", li)
ss[i], ss[li] = ss[li], ss[i]
// build new value by key paths, only for yaml.v2
// "site.info" -> map[interface{}]map[string]val
func buildValueByPath1(paths []string, val interface{}) (newItem map[interface{}]interface{}) {
if len(paths) == 1 {
return map[interface{}]interface{}{paths[0]: val}
}

arrutil.Reverse(paths)

// multi nodes
for _, p := range paths {
if newItem == nil {
newItem = map[interface{}]interface{}{p: val}
} else {
newItem = map[interface{}]interface{}{p: newItem}
}
}
return
}
87 changes: 43 additions & 44 deletions write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,146 +32,145 @@ func TestSetData(t *testing.T) {
}

func TestSet(t *testing.T) {
st := assert.New(t)

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

// clear old
ClearAll()
// err := LoadFiles("testdata/json_base.json")
err := LoadStrings(JSON, jsonStr)
st.Nil(err)
is.Nil(err)

val := String("name")
st.Equal("app", val)
is.Equal("app", val)

// empty key
err = Set("", "val")
st.Error(err)
is.Error(err)

// set new value: int
err = Set("newInt", 23)
if st.Nil(err) {
if is.Nil(err) {
iv := Int("newInt")
st.Equal(23, iv)
is.Equal(23, iv)
}

// set new value: int
err = Set("newBool", false)
if st.Nil(err) {
if is.Nil(err) {
bv := Bool("newBool")
st.False(bv)
is.False(bv)
}

// set new value: string
err = Set("newKey", "new val")
if st.Nil(err) {
if is.Nil(err) {
val = String("newKey")
st.Equal("new val", val)
is.Equal("new val", val)
}

// like yml decoded data
// like yaml.v2 decoded data
err = Set("ymlLike", map[interface{}]interface{}{"k": "v"})
st.Nil(err)
is.Nil(err)
str := c.String("ymlLike.k")
st.Equal("v", str)
is.Equal("v", str)

err = Set("ymlLike.nk", "nv")
st.Nil(err)
is.Nil(err)
str = c.String("ymlLike.nk")
st.Equal("nv", str)
is.Equal("nv", str)

// disable setByPath
err = Set("some.key", "val", false)
if st.Nil(err) {
if is.Nil(err) {
val = String("some")
st.Equal("", val)
is.Equal("", val)

val = String("some.key")
st.Equal("val", val)
is.Equal("val", val)
}
// fmt.Printf("%#v\n", c.Data())

// set value
err = Set("name", "new name")
if st.Nil(err) {
if is.Nil(err) {
val = String("name")
st.Equal("new name", val)
is.Equal("new name", val)
}

// set value to arr: by path
err = Set("arr1.1", "new val")
if st.Nil(err) {
if is.Nil(err) {
val = String("arr1.1")
st.Equal("new val", val)
is.Equal("new val", val)
}

// array only support add 1 level value
err = Set("arr1.1.key", "new val")
st.Error(err)
is.Error(err)

// set value to map: by path
err = Set("map1.key", "new val")
if st.Nil(err) {
if is.Nil(err) {
val = String("map1.key")
st.Equal("new val", val)
is.Equal("new val", val)
}

// more path nodes
err = Set("map1.info.key", "val200")
if st.Nil(err) {
if is.Nil(err) {
// fmt.Printf("%v\n", c.Data())
smp := StringMap("map1.info")
st.Equal("val200", smp["key"])
is.Equal("val200", smp["key"])

str = String("map1.info.key")
st.Equal("val200", str)
is.Equal("val200", str)
}

// new map
err = Set("map2.key", "new val")
if st.Nil(err) {
if is.Nil(err) {
val = String("map2.key")

st.Equal("new val", val)
is.Equal("new val", val)
}

// set new value: array(slice)
err = Set("newArr", []string{"a", "b"})
if st.Nil(err) {
if is.Nil(err) {
arr := Strings("newArr")

st.Equal(`[]string{"a", "b"}`, fmt.Sprintf("%#v", arr))
is.Equal(`[]string{"a", "b"}`, fmt.Sprintf("%#v", arr))

val = String("newArr.1")
st.Equal("b", val)
is.Equal("b", val)

val = String("newArr.100")
st.Equal("", val)
is.Equal("", val)
}

// set new value: map
err = Set("newMap", map[string]string{"k1": "a", "k2": "b"})
if st.Nil(err) {
if is.Nil(err) {
mp := StringMap("newMap")
st.NotEmpty(mp)
// st.Equal("map[k1:a k2:b]", fmt.Sprintf("%v", mp))
is.NotEmpty(mp)
// is.Equal("map[k1:a k2:b]", fmt.Sprintf("%v", mp))

val = String("newMap.k1")
st.Equal("a", val)
is.Equal("a", val)

val = String("newMap.notExist")
st.Equal("", val)
is.Equal("", val)
}

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

// Readonly
Default().Readonly()
st.True(c.Options().Readonly)
st.Error(Set("name", "new name"))
is.True(c.Options().Readonly)
is.Error(Set("name", "new name"))
}

func TestSet_fireEvent(t *testing.T) {
Expand Down

0 comments on commit 6d5e8a6

Please sign in to comment.