【问题标题】:Converting composed objects to json in Go在 Go 中将组合对象转换为 json
【发布时间】:2012-12-14 06:01:36
【问题描述】:

我是 Go 新手,不确定如何解决这个问题。在 OOP 术语中,我有一个 Animal 基类和两个 Cat 和 Dog 子类。我想为 Animal 指定一个适用于所有动物的 ToJson 方法。

我的问题是,当我调用 dog.ToJson() 时,我只得到 dog 的 Dog 属性,而没有得到 Animal 的属性。

如何使 ToJson 按预期工作(即with recursion)?

编辑:更改了代码以反映 lbonn 回答的建议,我无法按照我的意愿工作。 edit2:代码更改后的一致性问题

package main

import (
    "encoding/json"
    "fmt"
)

type Animal struct {
    Name string
}

type Cat struct {
    CatProperty int64
    Animal
}

type Dog struct {
    DogProperty int64
    Animal
}

func ToJson(i interface{}) []byte {
        data,err := json.Marshal(i)
    if err != nil {
        panic("???")
    }
    return data
}

func main() {
    dog := Dog{}
    dog.Name = "rex"
    dog.DogProperty = 2
    fmt.Println(string(ToJson(dog)))
    // Prints {"DogProperty":2}
    // I want it to print {"Name":"rex","DogProperty":2}
}

【问题讨论】:

    标签: json types go subclass


    【解决方案1】:

    匿名字段的 Json 编码已从 go 1 中删除。希望它将在 go 1.1 中恢复。有关详细信息,请参阅https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/jYMHbEv44r4

    因此,您现在可以使用标准库(使用 go 1)获得的最佳效果是 http://play.golang.org/p/LncNFeN8ys

    在 go 1.1 发布之前,您始终可以使用 skelterjohn 的补丁 https://github.com/skelterjohn/json/ 来支持匿名字段。

    或使用提示,从已修复此问题的源安装。见https://codereview.appspot.com/6460044

    【讨论】:

    • 我使用hg clone -r 492fdf07797e https://code.google.com/p/go 更新到最新版本,一切都很好,我的 json 正在按预期创建。感谢您提供的重要信息。
    【解决方案2】:

    这里,ToJson 方法适用于Dog 的匿名字段Animal。调用d.ToJson 只是d.Animal.ToJson 的可见性快捷方式。 GoLang Tutorials: Anonymous fields in struct

    在这里,我将编写一个函数而不是一个方法(Marshal 的简单包装):

    func ToJson(i interface{}) []byte {
        data,err := json.Marshal(i)
        if err != nil {
            panic("???")
        }
        return data
    }
    

    这不是特定于动物或狗,但实际上并不需要。

    更一般地说,go 中没有真正的继承概念。该语言中使用的对象范式与主流 OOP 完全不同,例如 Java 或 C++。 Go FAQ 提供了一些很好的说明。

    【讨论】:

    • 不幸的是我仍然不明白......来自golang.org/pkg/encoding/json/#Marshal我看到“元帅递归遍历值v”。我假设在我的示例中,它应该创建一个包含 DogProperty 的狗的 json 表示,并且(来自递归)还包括来自 Animal 的 Name 属性。但是当我打电话给 Marshal 时,结果不包括 Name。您能否帮助我理解这一点,最好发布一个给出 json {"DogProperty":2,"Name":"rex"} 的示例?另外,感谢您提供的有用链接,它帮助阐明了我对 Go 组合如何工作的理解。
    • 如果你想打印狗的所有值,你需要在整个狗对象上调用Marshal。在您的示例中,MarshalDog 内部的匿名字段 Animal 上被调用。因此,它看不到Dog 中不包含的字段。您可以尝试我在答案中发布的代码并使用fmt.Println(string(ToJson(d)),它将打印整个Dog
    • 请查看我对问题中代码的编辑,其中现在包含您的函数。它似乎不包括 Name 属性,我的输出中只得到{"DogProperty":2}
    • 嗯,它在我的机器上,这很奇怪。你用的是哪个版本的 go?
    • 我在 Ubuntu 12.04 上使用 go1.0.2。请参阅play.golang.org/p/wntp7n7K8Y,它也没有给出预期的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    相关资源
    最近更新 更多