本文介绍的是作者在使用golang的json库时发现的一个坑点,简单来说:
- 当json库Unmarshal到map或者struct中时,并不会默认将
[]byte
中没有提供的字段置为零值
场景
在服务中有配置以json形式存在于远程配置中心,需要不断拉取配置并Unmarshal到本地配置结构体中
但是在修改配置,进行功能验证的时候,发现部分配置的删除没有生效
最终排查发现是被删除的配置项是一个map[string]string
,在多次Unmarshal时,map不会被清除,只会加入,导致了问题
简单复现
经过试验,发现除了map,对于struct也有同样的问题,且无论是官方json库还是第三方库,都有存在这样的问题
实验代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package main
import ( "fmt"
jsoniter "github.com/json-iterator/go" )
type test struct { Str string `json:"str"` Str2 string `json:"str2"` }
func main() { var m map[string]string
b1 := `{ "key1" : "value1", "key2" : "value2" }` jsoniter.Unmarshal([]byte(b1), &m) fmt.Println(m) b2 := `{ "key3" : "value3"}` jsoniter.Unmarshal([]byte(b2), &m) fmt.Println(m)
t := test{} s1 := `{"str" :"s"}` jsoniter.Unmarshal([]byte(s1), &t) fmt.Printf("%+v\n", t) s2 := `{"str2" : "s2"}` jsoniter.Unmarshal([]byte(s2), &t) fmt.Printf("%+v\n", t) }
|
其打印结果为
1 2 3 4
| map[key1:value1 key2:value2] map[key1:value1 key2:value2 key3:value3] {Str:s Str2:} {Str:s Str2:s2}
|
解决方案
对于map或者struct,如果存在多次Unmarshal的情况,需要在Unmarshal之前手动清空