go 多层嵌套map的深层赋值与删除

背景

要对一个多层嵌套的json字符串里的某一个子key进行赋值或删除处理时,这个json串多个项目组共用,都可以修改,所以不能用一个固定的结构体来处理

赋值

支持对多层嵌套map的深层key进行赋值,不存在的key会自动创建

点击查看代码
func setNodeKeyVal(v map[string]interface{}, keys []string, val string) map[string]interface{} {
	lenKeys := len(keys)
	if 0 == lenKeys {
		return v
	}

	if 1 == lenKeys {
		v[keys[0]] = val
		return v
	}

	if sv, ok := v[keys[0]]; ok {
		v[keys[0]] = setNodeKeyVal(sv.(map[string]interface{}), keys[1:], val)
	} else {
		var tempVal interface{}
		tempVal = val

		for i := lenKeys - 1; i > 0; i-- {
			tv := make(map[string]interface{})
			tv[keys[i]] = tempVal
			tempVal = tv
		}

		v[keys[0]] = tempVal
	}
	return v
}

删除

支持对多层嵌套map的深层key进行删除,并会从提供的keys中,从底层key往上回溯查找,如果有空map则清理其key

点击查看代码
func delNodeKey(v map[string]interface{}, keys []string) map[string]interface{} {
	lenKeys := len(keys)
	if 0 == lenKeys {
		return v
	}

	if sv, ok := v[keys[0]]; ok {
		if 1 == lenKeys {
			delete(v, keys[0])
			return v
		}

		ssv := delNodeKey(sv.(map[string]interface{}), keys[1:])
		if 0 == len(ssv) {
			delete(v, keys[0])
		}
	}

	return v
}

测试

点击查看代码
func main() {
	testSet(`{}`, "val", []string{"xx", "yy", "zz"})
	testSet(`{"aaa":999}`, "666", []string{"xx", "yy", "zz"})
	testSet(`{"aa":{"aaa":666}}`, "111", []string{"xx", "yy", "zz"})

	testDel(`{"aa":{"aaa":666}}`, []string{"xx", "yy", "zz"})
	testDel(`{"aa":{"aaa":666}}`, []string{"aa", "aaa"})
	testDel(`{"aa":{"aaa":666, "bbb":999}}`, []string{"aa", "aaa"})
}

func testDel(s1 string, keys []string) {
	m1 := make(map[string]interface{})
	err := json.Unmarshal([]byte(s1), &m1)
	if nil != err {
		panic(err)
	}

	m2 := delNodeKey(m1, keys)
	js, err := json.Marshal(m2)
	if nil != err {
		panic(err)
	}

	fmt.Printf("del key\ninit data:%s\tkeys:%v\nresult data:%s\n\n", s1, keys, js)
}

func testSet(s1, val string, keys []string) {
	m1 := make(map[string]interface{})
	err := json.Unmarshal([]byte(s1), &m1)
	if nil != err {
		panic(err)
	}

	m2 := setNodeKeyVal(m1, keys, val)
	js, err := json.Marshal(m2)
	if nil != err {
		panic(err)
	}

	fmt.Printf("set key\ninit data:%s\tkeys:%v\t\tvalue:%s\nresult data:%s\n\n", s1, keys, val, js)
}

测试结果输出:

点击查看代码
set key
init data:{}    keys:[xx yy zz]         value:val
result data:{"xx":{"yy":{"zz":"val"}}}

set key
init data:{"aaa":999}   keys:[xx yy zz]         value:666
result data:{"aaa":999,"xx":{"yy":{"zz":"666"}}}

set key
init data:{"aa":{"aaa":666}}    keys:[xx yy zz]         value:111
result data:{"aa":{"aaa":666},"xx":{"yy":{"zz":"111"}}}

del key
init data:{"aa":{"aaa":666}}    keys:[xx yy zz]
result data:{"aa":{"aaa":666}}

del key
init data:{"aa":{"aaa":666}}    keys:[aa aaa]
result data:{}

del key
init data:{"aa":{"aaa":666, "bbb":999}} keys:[aa aaa]
result data:{"aa":{"bbb":999}}

posted @ 2022-11-01 19:25  Kim金  阅读(994)  评论(0)    收藏  举报