JSON nested struct to itself in Go Language

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

JSON nested struct to itself in Go Language

问题

我有以下的JSON数据:

[{
  "id": 8,
  "title": "Indonesia",
  "type": "country",
  "attributes": {
    "regionCode": "ID",
    "information": {
      "title": "Welcome to Indonesia",
      "content": "We only serve selected areas in Indonesia.",
      "image": "indo.png"
    }
  },
  "children": [
    {
      "id": 9,
      "title": "Jakarta",
      "type": "city",
      "attributes": {
        "regionCode": "ID-JKT",
        "information": {
          "title": "Welcome to Capital City of Indonesia",
          "content": "We only serve selected areas in Jabotabek",
          "image": "jakarta.png"
        }
      }       
    },
    {
      "id": 10,
      "title": "Bali",
      "type": "city",
      "attributes": {
        "regionCode": "ID-BAL",
        "information": {
          "title": "Welcome to the beach city Bali",
          "content": "We only serve selected areas in Bali.",
          "image": "bali.png"
        }   
      }       
    }
  ]
}]

从技术上讲,这是一个嵌套结构,其中子节点也可能有子节点。但是,当我使用unmarshal解码时,我无法得到正确的结果。

下面是一个可行的解决方案,假设我有locationAttribute结构体:

type locationNode []struct {
	ID         string             `json:"id"`
	Title      string             `json:"title"`
	Type       string             `json:"type"`
	Attributes locationAttribute `json:"attributes"`
	Children   []struct {
		ID         string             `json:"id"`
		Title      string             `json:"title"`
		Type       string             `json:"type"`
		Attributes locationAttribute `json:"attributes"`
		Children   []interface{}      `json:"children"`
	} `json:"children"`
}

然而,我希望它是这样的:

type locationNode []struct {
	ID         string             `json:"id"`
	Title      string             `json:"title"`
	Type       string             `json:"type"`
	Attributes locationAttribute `json:"attributes"`
	Children   []locationNode     `json:"children"`
}

如果有任何帮助,将不胜感激。

英文:

I have below JSON

[{
  "id": 8,
  "title": "Indonesia",
  "type": "country",
  "attributes": {
    "regionCode": "ID",
    "information": {
      "title": "Welcome to Indonesia",
      "content": "We only serve selected areas in Indonesia.",
      "image": "indo.png"
    }
  },
  "children": [
    {
      "id": 9,
      "title": "Jakarta",
      "type": "city",
      "attributes": {
        "regionCode": "ID-JKT",
        "information": {
          "title": "Welcome to Capital City of Indonesia",
          "content": "We only serve selected areas in Jabotabek",
          "image": "jakarta.png"
        }
      }       
    },
    {
      "id": 10,
      "title": "Bali",
      "type": "city",
      "attributes": {
        "regionCode": "ID-BAL",
        "information": {
          "title": "Welcome to the beach city Bali",
          "content": "We only serve selected areas in Bali.",
          "image": "bali.png"
        }   
      }       
    }
  ]
}]

Technically this is a nested structure to itself as the children node, and the children might have children as well. But i just couldnt get it right when im using unmarshal to decode this.

The working one is like below i have no problem defining the attribute as a separate struct so assuming i have locationAttribute struct

type locationNode []struct {
	ID         string             `json:"id"`
	Title      string             `json:"title"`
	Type       string             `json:"type"`
	Attributes locationAttribute `json:"attributes"`
	Children   []struct {
		ID         string             `json:"id"`
		Title      string             `json:"title"`
		Type       string             `json:"type"`
		Attributes locationAttribute `json:"attributes"`
		Children   []interface{}      `json:"children"`
	} `json:"children"`
}

However im expecting to be something like below

type locationNode []struct {
	ID         string             `json:"id"`
	Title      string             `json:"title"`
	Type       string             `json:"type"`
	Attributes locationAttribute `json:"attributes"`
	Children   []locationNode `json:"children"`
}

any help will be much appreciated

答案1

得分: 1

使用https://mholt.github.io/json-to-go/,您的JSON转换为:

type AutoGenerated struct {
    ID int `json:"id"`
    Title string `json:"title"`
    Type string `json:"type"`
    Attributes struct {
        RegionCode string `json:"regionCode"`
        Information struct {
            Title string `json:"title"`
            Content string `json:"content"`
            Image string `json:"image"`
        } `json:"information"`
    } `json:"attributes"`
    Children []struct {
        ID int `json:"id"`
        Title string `json:"title"`
        Type string `json:"type"`
        Attributes struct {
            RegionCode string `json:"regionCode"`
            Information struct {
                Title string `json:"title"`
                Content string `json:"content"`
                Image string `json:"image"`
            } `json:"information"`
        } `json:"attributes"`
    } `json:"children"`
}
英文:

Using https://mholt.github.io/json-to-go/ your JSON converts to

type AutoGenerated struct {
	ID int `json:"id"`
	Title string `json:"title"`
	Type string `json:"type"`
	Attributes struct {
		RegionCode string `json:"regionCode"`
		Information struct {
			Title string `json:"title"`
			Content string `json:"content"`
			Image string `json:"image"`
		} `json:"information"`
	} `json:"attributes"`
	Children []struct {
		ID int `json:"id"`
		Title string `json:"title"`
		Type string `json:"type"`
		Attributes struct {
			RegionCode string `json:"regionCode"`
			Information struct {
				Title string `json:"title"`
				Content string `json:"content"`
				Image string `json:"image"`
			} `json:"information"`
		} `json:"attributes"`
	} `json:"children"`
}

答案2

得分: 1

除了 JSON 文本中的 "id" 字段是一个数字而不是 string,对我来说它是有效的。

为了缩短示例,省略了 "attributes"

type locationNode struct {
    ID       int            `json:"id"`
    Title    string         `json:"title"`
    Type     string         `json:"type"`
    Children []locationNode `json:"children"`
}

func main() {
    ln := locationNode{}

    err := json.Unmarshal([]byte(src), &ln)

    fmt.Printf("%+v %v\n", ln, err)
}

const src = `{
  "id": 8,
  "title": "Indonesia",
  "type": "country",
  "attributes": {
    "regionCode": "ID",
    "information": {
      "title": "Welcome to Indonesia",
      "content": "We only serve selected areas in Indonesia.",
      "image": "indo.png"
    }
  },
  "children": [
    {
      "id": 9,
      "title": "Jakarta",
      "type": "city",
      "attributes": {
        "regionCode": "ID-JKT",
        "information": {
          "title": "Welcome to Capital City of Indonesia",
          "content": "We only serve selected areas in Jabotabek",
          "image": "jakarta.png"
        }
      }       
    },
    {
      "id": 10,
      "title": "Bali",
      "type": "city",
      "attributes": {
        "regionCode": "ID-BAL",
        "information": {
          "title": "Welcome to the beach city Bali",
          "content": "We only serve selected areas in Bali.",
          "image": "bali.png"
        }   
      }       
    }
  ]
}`

输出结果(在 Go Playground 上尝试):

{ID:8 Title:Indonesia Type:country Children:[{ID:9 Title:Jakarta Type:city Children:[]} {ID:10 Title:Bali Type:city Children:[]}]} <nil>
英文:

Besides the fact that in the JSON text the &quot;id&quot; field is a number and not string, it works for me.

Omitting the &quot;attributes&quot; to make the example shorter:

type locationNode struct {
	ID       int            `json:&quot;id&quot;`
	Title    string         `json:&quot;title&quot;`
	Type     string         `json:&quot;type&quot;`
	Children []locationNode `json:&quot;children&quot;`
}

func main() {
	ln := locationNode{}

	err := json.Unmarshal([]byte(src), &amp;ln)

	fmt.Printf(&quot;%+v %v\n&quot;, ln, err)
}

const src = `{
  &quot;id&quot;: 8,
  &quot;title&quot;: &quot;Indonesia&quot;,
  &quot;type&quot;: &quot;country&quot;,
  &quot;attributes&quot;: {
    &quot;regionCode&quot;: &quot;ID&quot;,
    &quot;information&quot;: {
      &quot;title&quot;: &quot;Welcome to Indonesia&quot;,
      &quot;content&quot;: &quot;We only serve selected areas in Indonesia.&quot;,
      &quot;image&quot;: &quot;indo.png&quot;
    }
  },
  &quot;children&quot;: [
    {
      &quot;id&quot;: 9,
      &quot;title&quot;: &quot;Jakarta&quot;,
      &quot;type&quot;: &quot;city&quot;,
      &quot;attributes&quot;: {
        &quot;regionCode&quot;: &quot;ID-JKT&quot;,
        &quot;information&quot;: {
          &quot;title&quot;: &quot;Welcome to Capital City of Indonesia&quot;,
          &quot;content&quot;: &quot;We only serve selected areas in Jabotabek&quot;,
          &quot;image&quot;: &quot;jakarta.png&quot;
        }
      }       
    },
    {
      &quot;id&quot;: 10,
      &quot;title&quot;: &quot;Bali&quot;,
      &quot;type&quot;: &quot;city&quot;,
      &quot;attributes&quot;: {
        &quot;regionCode&quot;: &quot;ID-BAL&quot;,
        &quot;information&quot;: {
          &quot;title&quot;: &quot;Welcome to the beach city Bali&quot;,
          &quot;content&quot;: &quot;We only serve selected areas in Bali.&quot;,
          &quot;image&quot;: &quot;bali.png&quot;
        }   
      }       
    }
  ]
}`

Output (try it on the Go Playground):

{ID:8 Title:Indonesia Type:country Children:[{ID:9 Title:Jakarta Type:city Children:[]} {ID:10 Title:Bali Type:city Children:[]}]} &lt;nil&gt;

答案3

得分: 0

好的,我已经解决了这个问题 - 实际上是一个愚蠢的粗心错误,因为我的结构体已经是一个数组,所以我不应该将children定义为一个数组。

所以下面的定义是正确的:

type locationNode []struct {
  ID         string             `json:"id"`
  Title      string             `json:"title"`
  Type       string             `json:"type"`
  Attributes locationAttribute  `json:"attributes"`
  Children   locationNode       `json:"children"`
}
英文:

Okay I managed to resolve this - it's actually a silly careless mistake, since my struct is already an array I should NOT define the children as an array.

So below definition works

type locationNode []struct {
  ID         string             `json:&quot;id&quot;`
  Title      string             `json:&quot;title&quot;`
  Type       string             `json:&quot;type&quot;`
  Attributes locationAttribute  `json:&quot;attributes&quot;`
  Children   locationNode     `json:&quot;children&quot;`
}

答案4

得分: 0

看起来,按照你期望的方式定义Children是可以正常工作的。以下代码既可以正确地进行编组(marshal),也可以进行解组(unmarshal)。

type Bob struct {
    ID         string            `json:"id"`
    Title      string            `json:"title"`
    Type       string            `json:"type"`
    Attributes int               `json:"attributes"`
    Children   []Bob             `json:"children"`
}

Playground链接

英文:

It certainly looks like defining Children in the way you expect works fine. The following both marshals and unmarshals fine.

type Bob struct {
	ID         string            `json:&quot;id&quot;`
	Title      string            `json:&quot;title&quot;`
	Type       string            `json:&quot;type&quot;`
	Attributes int               `json:&quot;attributes&quot;`
	Children   []Bob             `json:&quot;children&quot;`
}

Playground link

huangapple
  • 本文由 发表于 2017年1月6日 17:45:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/41502902.html
匿名

发表评论

匿名网友

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

确定