如何在结构体内部包含多个结构体?

huangapple go评论90阅读模式
英文:

How to have many structs inside a struct?

问题

我有一个名为ClassDetails的结构体,像这样:

type ClassDetails struct {
    ClassNumber int      `json:"classNumber"`
    Names       []string `json:"names"`
}

我手动创建了一个类似这样的结构体:

type Subject struct {
    Math    ClassDetails `json:"math"`
    Science ClassDetails `json:"science"`
}

我想要在运行时动态地添加更多的ClassDetails到Subject中,但是我不能使用Class类型的数组。如何实现这个功能?我还需要将类的名称添加为json标签。我的结果结构体应该保存如下的值:

{
    "classes": {
        "school": "MayorWestHigh",
        "math": [
            {
                "classNumber": "1",
                "names": ["aaron", "baron", "cathy"]
            },
            {
                "classNumber": "2",
                "names": ["aaron", "baron", "cathy"]
            }
        ],
        "science": [
            {
                "classNumber": "1",
                "names": ["ted", "baron", "isiah"]
            }
        ],
        "geography": [
            {
                "classNumber": "1",
                "names": ["peter", "glen", "joe"]
            }
        ]
    }
}
英文:

I have a struct of called class like this.

type ClassDetails struct {
ClassNumber int `json:"classNumber"`
Names []string `json:names`}

I have manually created something like this.

type Subject struct {
Math ClassDetails `json:"math"`
Science ClassDetails `json:"science"`}

I want to do this on the fly. Add more ClassDetails to the Subject as I get information, but I cannot use an array of type class.
How can this be done? And I also need to add the names of the classes as the json tag.
My resultant struct should hold values like this.

{
	"classes": {
		"school": "MayorWestHigh",
		"math": [{
				"classNumber": "1",
				"names": ["aaron", "baron", "cathy"]
			},
			{
				"classNumber": "2",
				"names": ["aaron", "baron", "cathy"]
			}
		],
		"science": [{
			"classNumber": "1",
			"names": ["ted", "baron", "isiah"]
		}],
		"geography": [{
			"classNumber": "1",
			"names": ["peter", "glen", "joe"]
		}]

	}
}

答案1

得分: 2

不要回答我要翻译的问题。以下是要翻译的内容:

不要静态定义每个科目,而是使用一个从科目名称到班级详细信息数组的映射,如何?

通过使用我上面描述的映射,并将映射嵌入到结构体中,你可以非常接近你想要的JSON,如下所示:

type ClassDetails struct {
    ClassNumber int      `json:"classNumber"`
    Names       []string `json:"names"`
}

type Subjects map[string][]ClassDetails

type Classes struct {
    School   string   `json:"school"`
    Subjects Subjects
}

上述Classes结构体的一个实例将填充你所需JSON的以下部分:

{
    "classes": {
        ... Classes实例放在这里...
    }
}

剩余的外部对象可以按照以下方式构建:

c := Classes{...}
outer := map[string]Classes{"classes": c}

使用正确初始化的数据对outer对象进行JSON编组,几乎可以得到与你所需的JSON完全相同的结果(要完全匹配,你需要将ClassNumber转换为字符串类型)。

这是一个Go Playground链接,它使用精确的数据初始化这些结构体,并漂亮地打印出你的JSON:https://play.golang.org/p/HFMbHtY2os

编辑:这仍然不完全符合你问题中的JSON,因为它会在其中添加一个名为"Subjects"的新对象。问题在于你的JSON中"classes"内部的对象混合了类型,而Go不能声明动态结构字段。

如果你真的必须使用那种JSON结构,你需要使用更通用的map[string]interface{},以允许对象层次结构中的同一级别上的混合类型。这是另一个Go Playground链接,其中包含正确的实现:https://play.golang.org/p/rlYTYGofSI

英文:

Instead of statically defining each subject, how about simply using a map from subject name => array of class details ?

One way you can get very close to the JSON you want by using a map like I described above, and by embedding the map into a struct as follows:

type ClassDetails struct {
	ClassNumber int      `json:"classNumber"`
	Names       []string `json:names`
}

type Subjects map[string][]ClassDetails

type Classes struct {
	School string `json:"school"`
	Subjects
}

An instance of the Classes struct above would fill in the following part of your desired JSON:

{
  "classes": {
    ... the Classes instance goes here...
  }
}

The remaining outer object can just be constructed as follows:

c := Classes{...}
outer := map[string]Classes{"classes": c}

A JSON marshal of the outer object, with the right data initialized, arrives at almost exactly your JSON above (to match it exactly you'd have to turn the ClassNumber into a string type).

Here is a Go Playground link that initializes these structs with the exact data you want and pretty-prints your JSON: https://play.golang.org/p/HFMbHtY2os

EDIT: This still doesn't exactly match the JSON in your question, as it will add a new object in there called "Subjects". The problem is that the object inside of "classes" in your JSON mixes types, and Go can't declare dynamic struct fields.

If you really have to use that JSON structure, you'll need to go with the more generic map[string]interface{} to allow mixed types at the same level in your object hierarchy. Here's another Go Playground link that has the correct implementation: https://play.golang.org/p/rlYTYGofSI

huangapple
  • 本文由 发表于 2017年8月23日 12:51:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/45830855.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定