Golang json序列化/反序列化递归数据模型



假设我有:

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上试试这个

相关内容

  • 没有找到相关文章

最新更新