在上一篇文章中咱們介紹瞭如何使用gjson
快速讀取 JSON 串中的值。爲了內容的完整性,今天咱們介紹一下如何使用sjson
快速設置 JSON 串中的值。git
先安裝:github
$ go get github.com/tidwall/sjson
後使用:json
package mainimport ( "fmt" "github.com/tidwall/sjson")const json = `{"name":{"first":"li","last":"dj"},"age":18}`func main() { value, _ := sjson.Set(json, "name.last", "dajun") fmt.Println(value)}
上面代碼經過sjson.Set()
將 JSON 串中name.last
對應的值設置爲dajun
。與gjson
同樣,sjson
也經過鍵路徑指定具體的位置,鍵路徑即爲一系列以.
分隔的鍵。sjson
支持的鍵路徑語法是gjson
的一個子集,具體鍵路徑的語法能夠參見上一篇文章。sjson.Set()
返回設置以後的 JSON 串。最終程序輸出:數組
{"name":{"first":"li","last":"dajun"},"age":18}
sjson
支持的類型包括nil/bool/int/float/string
等。若是傳入sjson
不支持的類型,sjson
會調用json.Marshal
,而後將生成的字符串設置到對應的鍵路徑上:微信
type User struct { Name string `json:"name"` Age int `json:"age"`}func main() { nilJSON, _ := sjson.Set("", "key", nil) fmt.Println(nilJSON) boolJSON, _ := sjson.Set("", "key", false) fmt.Println(boolJSON) intJSON, _ := sjson.Set("", "key", 1) fmt.Println(intJSON) floatJSON, _ := sjson.Set("", "key", 10.5) fmt.Println(floatJSON) strJSON, _ := sjson.Set("", "key", "hello") fmt.Println(strJSON) mapJSON, _ := sjson.Set("", "key", map[string]interface{}{"hello": "world"}) fmt.Println(mapJSON) u := User{Name: "dj", Age: 18} structJSON, _ := sjson.Set("", "key", u) fmt.Println(structJSON)}
注意,咱們傳入一個空字符串,sjson.Set()
會生成一個空對象,而後按照鍵路徑依次設置值。下面分析上述程序輸出:app
nil
:在 JSON 中用null
表示,輸出{"key":null}
;false
:在 JSON 中布爾值用true/false
表示,輸出{"key":false}
;1
和10.5
:整數和浮點數在 JSON 中都用number
表示,分別輸出{"key":1}
和{"key":10.5}
;hello
:輸出{"key":"hello"}
;map[string]interface{}
:sjson
並不原生支持map
類型,故經過json.Marshal
將其序列化爲{"hello":"world"}
再設置到鍵key
上,輸出{"key":{"hello":"world"}}
;User
對象:先經過json.Marshal
序列化爲{"name":"dj","age":18}
再設置;修改數組能夠經過在鍵路徑後添加索引,有兩種特殊狀況:性能
-1
或數組長度爲索引表示在數組後添加一個新元素;null
值。看下面示例:學習
func main() { fruits := `{"fruits":["apple", "orange", "banana"]}` var newValue string newValue, _ = sjson.Delete(fruits, "fruits.1") fmt.Println(newValue) newValue, _ = sjson.Delete(fruits, "fruits.-1") fmt.Println(newValue) newValue, _ = sjson.Set(fruits, "fruits.5") fmt.Println(newValue)}
fruits.1
:設置第二個水果爲grape
(索引從 0 開始),輸出{"fruits":["apple", "grape", "banana"]}
;fruits.3
:因爲數組長度爲 3,使用 3 表示在數組後添加一個元素,輸出{"fruits":["apple","orange","banana","pear"]}
;fruits.-1
:使用-1
一樣表示在數組後添加一個元素,輸出{"fruits":["apple", "orange", "banana","strawberry"]}
;fruits.5
:索引 5 已經大於數組長度 3 了,因此會多出兩個null
,輸出{"fruits":["apple","orange","banana",null,null,"watermelon"]}
。刪除數組元素須要調用sjson.Delete()
方法,鍵路徑語法相同。若是鍵路徑對應的值不存在,則Delete()
無效果:ui
func main() { var newValue string user := `{"name":{"first":"li","last":"dj"},"age":18}` newValue, _ = sjson.Delete(user, "name.first") fmt.Println(newValue) newValue, _ = sjson.Delete(user, "name.full") fmt.Println(newValue) fruits := `{"fruits":["apple", "orange", "banana"]}` newValue, _ = sjson.Delete(fruits, "fruits.1") fmt.Println(newValue) newValue, _ = sjson.Delete(fruits, "fruits.-1") fmt.Println(newValue) newValue, _ = sjson.Delete(fruits, "fruits.5") fmt.Println(newValue)}
name.first
:刪除字段name.first
,輸出{"name":{"last":"dj"},"age":18}
;name.full
:因爲字段name.full
不存在,無效果,輸出{"name":{"first":"li","last":"dj"},"age":18}
;fruits.1
:刪除數組fruits
的第二個元素,輸出{"fruits":["apple", "banana"]}
;fruits.-1
:刪除數組最後一個元素,輸出{"fruits":["apple", "orange"]}
;fruits.5
:索引 5 超出數組長度 3,無效果,輸出{"fruits":["apple", "orange", "banana"]}
。使用sjson
出現的錯誤分爲兩種,一種是傳入的 JSON 串不是合法的串,另外一種是鍵路徑語法錯誤。Set()
和Delete()
方法返回的第二個參數爲錯誤,只有非法的鍵路徑會返回錯誤,非法 JSON 串不會。spa
同gjson
同樣,sjson
一樣不會檢查傳入的 JSON 串的合法性,它假設傳入的是合法的串。若是傳入一個非法的 JSON 串,程序輸出不肯定的結果:
func main() { user := `{"name":dj,age:18}` newValue, err := sjson.Set(user, "name", "dajun") fmt.Println(err, newValue)}
上面程序中,我故意傳入一個非法的 JSON 串(dj
和age
漏掉了雙引號)。最終程序輸出:
<nil> {"name":dj,age:"dajun"}
將age
變爲了dajun
,顯然不正確。然而此時返回的err = nil
。
與gjson
相比,sjson
能使用的鍵路徑語法比較有限,不能使用通配符和一些條件語法。若是傳入的鍵路徑非法,將返回非空的錯誤值:
func main() { user := `{"name":"dj","age":18}` newValue, err := sjson.Set(user, "na?e", "dajun") fmt.Println(err, newValue)}
上次使用通配符?
,輸出:
wildcard characters not allowed in path
sjson
比較簡單易用,性能不俗。咱們在肯定 JSON 串合法的狀況下,可以使用它快速設置值。
你們若是發現好玩、好用的 Go 語言庫,歡迎到 Go 每日一庫 GitHub 上提交 issue😄
我
-
歡迎關注個人微信公衆號【GoUpUp】,共同窗習,一塊兒進步~