我有一个我想要编组给JSON的结构。它有一个名为Foo
的定义字段(导出为foo
)和一个data
接口字段,我希望通过该字段传递带有其他JSON字段的动态结构。
但是,当数据字段是接口而不是特定结构时,它永远不会导出为JSON。我怎样才能做到这一点?
package main
import (
"encoding/json"
"fmt"
)
type data interface{}
type foo struct {
Foo string `json:"foo,omitempty"`
data
}
type bar struct {
Bar string `json:"bar,omitempty"`
}
func main() {
b := bar{"bar"}
f := foo{"foo", b}
byt, err := json.Marshal(f)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(byt))
}
我需要输出看起来像这样(它需要是扁平的,而不是嵌套的):
{"foo": "foo", "bar": "bar"}
答案 0 :(得分:4)
您可以使用自定义json.Marshaler实现和一些字节切片来完成此操作。
func (f foo) MarshalJSON() ([]byte, error) {
type goo foo
g := goo(f)
b1, err := json.Marshal(g)
if err != nil {
return nil, err
}
b2, err := json.Marshal(g.data)
if err != nil {
return nil, err
}
s1 := string(b1[:len(b1)-1])
s2 := string(b2[1:])
return []byte(s1 + ", " + s2), nil
}
https://play.golang.org/p/NYTNWIL-xu
请注意,这不是检查字节是否可以实际切片,也不考虑data
字段是切片或数组的可能情况,我不确定你是怎么回事无论如何都会想要那么扁平化。
答案 1 :(得分:1)
我会编写一个自定义编组器,如下所示:
func (f foo) MarshalJSON() ([]byte, error) {
type tmp foo
g := tmp(f)
first, err := json.Marshal(g)
if err != nil {
return nil, err
}
second, err := json.Marshal(f.data)
if err != nil {
return nil, err
}
data := make(map[string]interface{})
json.Unmarshal(first, &data)
json.Unmarshal(second, &data)
return json.Marshal(data)
//{"bar":"bar","foo":"foo"}
}
答案 2 :(得分:0)
2个选项:
设置为json.RawMessage
类型,因此不会自动解码并保留为接口。 https://golang.org/pkg/encoding/json/#RawMessage
在结构上编写自定义解组程序。