Go 每日一庫之 sjson

簡介

上一篇文章中咱們介紹瞭如何使用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}
  • 110.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

非法 JSON 串

gjson同樣,sjson一樣不會檢查傳入的 JSON 串的合法性,它假設傳入的是合法的串。若是傳入一個非法的 JSON 串,程序輸出不肯定的結果:

func main() {  user := `{"name":dj,age:18}`  newValue, err := sjson.Set(user, "name", "dajun")  fmt.Println(err, newValue)}

上面程序中,我故意傳入一個非法的 JSON 串(djage漏掉了雙引號)。最終程序輸出:

<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😄

參考

  1. sjson GitHub:https://github.com/tidwall/sjson
  2. Go 每日一庫 GitHub:https://github.com/darjun/go-daily-lib


-

個人博客:https://darjun.github.io

歡迎關注個人微信公衆號【GoUpUp】,共同窗習,一塊兒進步~

相關文章
相關標籤/搜索