假设我有:
type IObject interface {
}
type Item struct {
Description string
Data []byte
}
type FunctionX1 struct {
Object IInclusionObject
}
type FunctionX2 struct {
Object1 IInclusionObject
Object2 IInclusionObject
}
我希望能够序列化/反序列化一个模型,其中Item
, FunctionX1
, FunctionX2
它们都实现了IObject
,并且它们可以任意深度地指向彼此。
注意,我不希望:FunctionX1{Item{"foo", []byte("bar")}}
被序列化为:
"object": {
"Description": "foo"
"Data": ...
}
而是:
"FunctionX1": {
"item": {
"Description": "foo"
"Data": ...
}
}
我是否需要做我自己的JSON编组器-似乎我不能使用现有的。
相关问题,以防我需要我自己的。是否有JSON美化器,我可以流有效的,但随机格式化的JSON,它输出漂亮的版本(注意JSON可能是显着大-我不想生成,解析生成格式化)。
使用wrapper (struct or map)
可以使用结构体标签将结构体的字段映射到JSON中的不同名称。这样你就可以把"Object"
改成"item"
:
type FunctionX1 struct {
Object IInclusionObject `json:"item"`
}
但是如果您希望"FunctionX1"
出现在JSON文本中,您仍然需要一个包装器结构或映射。例如:
f := FunctionX1{Item{"foo", []byte("bar")}}
if data, err := json.Marshal(map[string]interface{}{"FunctionX1": f}); err != nil {
panic(err)
} else {
fmt.Println(string(data))
}
输出:{"FunctionX1":{"item":{"Description":"foo","Data":"YmFy"}}}
或者使用包装结构体:
type Wrapper struct {
FunctionX1 FunctionX1
}
f := FunctionX1{Item{"foo", []byte("bar")}}
if data, err := json.Marshal(Wrapper{f}); err != nil {
panic(err)
} else {
fmt.Println(string(data))
}
输出相同:
{"FunctionX1":{"item":{"Description":"foo","Data":"YmFy"}}}
如果你想要漂亮的JSON格式,你可以使用json.MarshalIndent()
来做封送:
if data, err := json.MarshalIndent(Wrapper{f}, "", " "); err != nil {
panic(err)
} else {
fmt.Println(string(data))
}
输出:{
"FunctionX1": {
"item": {
"Description": "foo",
"Data": "YmFy"
}
}
}
试试Go Playground上所有的例子。
使用自定义封送处理
如果您不想使用包装器结构或映射,则需要使用自定义封送,但这非常简单:
type FunctionX1 struct {
Object IInclusionObject `json:"item"`
}
func (f FunctionX1) MarshalJSON() ([]byte, error) {
type FunctionX1_ FunctionX1
return json.Marshal(map[string]interface{}{"FunctionX1": FunctionX1_(f)})
}
我们有效地将包装移动到MarshalJSON()
方法中,因此FunctionX1
的其他封送值不必这样做。
f := FunctionX1{Item{"foo", []byte("bar")}}
if data, err := json.Marshal(f); err != nil {
panic(err)
} else {
fmt.Println(string(data))
}
if data, err := json.MarshalIndent(f, "", " "); err != nil {
panic(err)
} else {
fmt.Println(string(data))
}
注意MarshalJSON()
里面的新FunctionX1_
类型是为了避免无限的"递归"。
{"FunctionX1":{"item":{"Description":"foo","Data":"YmFy"}}}
{
"FunctionX1": {
"item": {
"Description": "foo",
"Data": "YmFy"
}
}
}
在Go Playground上试试这个