go-simplejson 插入数组

go-simplejson是go lang语言中操作json非常方便的开源库。最近使用simplejson进行数据插入操作时遇到了问题,经过排查后最终解决。现记录如下。

# 问题描述

 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
// 创建了一个json对象J,需要从其他地方获取剩余json信息后,插入到J中的data字段中。初始版本如下:
import (
	"fmt"

	simplejson "github.com/bitly/go-simplejson"
)

func main() {
	js, _ := simplejson.NewJson([]byte(`
{
"errno": 0,
"errmsg": "test"
}`))

	var js_2 = new(simplejson.Json)
	*js_2 = *js
	jsArr := []*simplejson.Json{}
	js1, _ := simplejson.NewJson([]byte(`{"num": 1}`))
	js2, _ := simplejson.NewJson([]byte(`{"num": 2}`))
	jsArr = append(jsArr, js1)
	jsArr = append(jsArr, js2)
	js.Set("data", jsArr)
	js.Get("data").GetIndex(0).Set("test", 1)
	jsB, _ := js.MarshalJSON()
	fmt.Println(string(jsB)) 
}
// % go run js_check.go
// {"data":[{"num":1},{"num":2}],"errmsg":"test","errno":0}

# 问题排查

经过dlv逐行调试,实际问题出在js.Get("data").GetIndex(0).Set("test", 1)中。跳转至定义,该操作实际做如下转换:

1
2
3
4
arr, ok := js.Get("data").data.([]interface{})
if ok {
    &simplejson.Json(arr[index]).Set("test", 1)
}

这里由于jsArr[]*simplejson.Json,类型断言为[]interface{}失败。所以无法正常设置值。查看simplejson.go,其中的Json对象结构如下:

1
2
3
type Json struct {
    data interface{}
}

其实可以通过js.Interface()获取其中的真实数据。

# 解决方案

变更为如下代码即可:

 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
package main

import (
	"fmt"

	simplejson "github.com/bitly/go-simplejson"
)

func main() {
	js, _ := simplejson.NewJson([]byte(`
{
"errno": 0,
"errmsg": "test"
}`))

	var js_2 = new(simplejson.Json)
	*js_2 = *js
	jsArr := []interface{}{}
	js1, _ := simplejson.NewJson([]byte(`{"num": 1}`))
	js2, _ := simplejson.NewJson([]byte(`{"num": 2}`))
	jsArr = append(jsArr, js1.Interface())
	jsArr = append(jsArr, js2.Interface())
	js.Set("data", jsArr)
	js.Get("data").GetIndex(0).Set("test", 1)
	jsB, _ := js.MarshalJSON()
	fmt.Println(string(jsB))
}
// % go run js_check.go
// {"data":[{"num":1,"test":1},{"num":2}],"errmsg":"test","errno":0}
Hello, World!
使用 Hugo 构建
主题 StackJimmy 设计