让我说我有:
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可能非常大 - 我不想生成,解析生成格式化)。
答案 0 :(得分:2)
您可以使用struct tags将结构的字段映射到JSON中的不同名称。因此,您可以将"Object"
更改为"item"
:
type FunctionX1 struct {
Object IInclusionObject `json:"item"`
}
但是,如果希望{J}文本中出现"FunctionX1"
,则仍需要包装器结构或映射。例如:
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))
}
请注意,FunctionX1_
内的新MarshalJSON()
类型是为了避免无限的"递归"。
输出:
{"FunctionX1":{"item":{"Description":"foo","Data":"YmFy"}}}
{
"FunctionX1": {
"item": {
"Description": "foo",
"Data": "YmFy"
}
}
}
在Go Playground上试试这个。