在go中创建异构json数组
Create heterogeneous json array in go
假设我在 go 中有这样的结构:
type Message struct {
Args []interface{}
Kwargs map[string]interface{}
}
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
我应该如何整理消息以获得这样的 JSON?
[[1,2,3,4], {"a": 2, "b":3}]
你想要的输出是一个 JSON 数组,其中包含你的 message
结构值的 Args
和 Kwargs
字段,所以你可能会得到你想要的通过编组以下切片值:
[]interface{}{message.Args, message.Kwargs}
例如:
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
err := json.NewEncoder(os.Stdout).
Encode([]interface{}{message.Args, message.Kwargs})
fmt.Println(err)
上面的输出(在Go Playground上试试):
[[1,2,3,4],{"a":2,"b":3}]
<nil>
这适用于这种特定情况。如果你想要一个像数组元素一样编组结构值字段的通用解决方案,你可以创建一个辅助函数,将 "packs" 字段放入切片中:
func getFields(i interface{}) (res []interface{}) {
v := reflect.ValueOf(i)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil
}
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if f.CanInterface() {
res = append(res, f.Interface())
}
}
return res
}
上面的 getFields()
接受结构值和指向结构的指针。使用示例:
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
err := json.NewEncoder(os.Stdout).Encode(getFields(message))
fmt.Println(err)
err = json.NewEncoder(os.Stdout).Encode(getFields(&message))
fmt.Println(err)
输出(在 Go Playground 上尝试):
[[1,2,3,4],{"a":2,"b":3}]
<nil>
[[1,2,3,4],{"a":2,"b":3}]
<nil>
您可以向结构中添加编组方法来处理逻辑。
行中的内容
func (m Message) MarshalJSON() ([]byte, error) {
data := make([]interface{}, 0)
data = append(data, m.Args)
data = append(data, m.Kwargs)
return json.Marshal(data)
}
假设我在 go 中有这样的结构:
type Message struct {
Args []interface{}
Kwargs map[string]interface{}
}
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
我应该如何整理消息以获得这样的 JSON?
[[1,2,3,4], {"a": 2, "b":3}]
你想要的输出是一个 JSON 数组,其中包含你的 message
结构值的 Args
和 Kwargs
字段,所以你可能会得到你想要的通过编组以下切片值:
[]interface{}{message.Args, message.Kwargs}
例如:
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
err := json.NewEncoder(os.Stdout).
Encode([]interface{}{message.Args, message.Kwargs})
fmt.Println(err)
上面的输出(在Go Playground上试试):
[[1,2,3,4],{"a":2,"b":3}]
<nil>
这适用于这种特定情况。如果你想要一个像数组元素一样编组结构值字段的通用解决方案,你可以创建一个辅助函数,将 "packs" 字段放入切片中:
func getFields(i interface{}) (res []interface{}) {
v := reflect.ValueOf(i)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil
}
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if f.CanInterface() {
res = append(res, f.Interface())
}
}
return res
}
上面的 getFields()
接受结构值和指向结构的指针。使用示例:
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
err := json.NewEncoder(os.Stdout).Encode(getFields(message))
fmt.Println(err)
err = json.NewEncoder(os.Stdout).Encode(getFields(&message))
fmt.Println(err)
输出(在 Go Playground 上尝试):
[[1,2,3,4],{"a":2,"b":3}]
<nil>
[[1,2,3,4],{"a":2,"b":3}]
<nil>
您可以向结构中添加编组方法来处理逻辑。
行中的内容func (m Message) MarshalJSON() ([]byte, error) {
data := make([]interface{}, 0)
data = append(data, m.Args)
data = append(data, m.Kwargs)
return json.Marshal(data)
}