如何将 JSON 解码为结构体(structs)?

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

How to decode json into structs

问题

我正在尝试在Go中解码一些JSON,但是某些字段没有被解码。

我只需要MX记录,所以我没有定义其他字段。根据godoc的理解,您不需要定义您不使用/不需要的字段。

以下是代码示例:

package main

import "fmt"
import "encoding/json"

func main() {

    body := `
      {"response": {
      "status": "SUCCESS",
      "data": {
        "mxRecords": [
          {
            "value": "us2.mx3.mailhostbox.com.",
            "ttl": 1,
            "priority": 100,
            "hostName": "@"
          },
          {
            "value": "us2.mx1.mailhostbox.com.",
            "ttl": 1,
            "priority": 100,
            "hostName": "@"
          },
          {
            "value": "us2.mx2.mailhostbox.com.",
            "ttl": 1,
            "priority": 100,
            "hostName": "@"
          }
        ],
        "cnameRecords": [
          {
            "aliasHost": "pop.a.co.uk.",
            "canonicalHost": "us2.pop.mailhostbox.com."
          },
          {
            "aliasHost": "webmail.a.co.uk.",
            "canonicalHost": "us2.webmail.mailhostbox.com."
          },
          {
            "aliasHost": "smtp.a.co.uk.",
            "canonicalHost": "us2.smtp.mailhostbox.com."
          },
          {
            "aliasHost": "imap.a.co.uk.",
            "canonicalHost": "us2.imap.mailhostbox.com."
          }
        ],
        "dkimTxtRecord": {
          "domainname": "20a19._domainkey.a.co.uk",
          "value": "\"v=DKIM1; g=*; k=rsa; p=DkfbhO8Oyy0E1WyUWwIDAQAB\"",
          "ttl": 1
        },
        "spfTxtRecord": {
          "domainname": "a.co.uk",
          "value": "\"v=spf1 redirect=_spf.mailhostbox.com\"",
          "ttl": 1
        },
        "loginUrl": "us2.cp.mailhostbox.com"
      }
    }}`

    type MxRecords struct {
        Value    string
        Ttl      int
        Priority int
        HostName string
    }

    type Data struct {
        MxRecords []MxRecords
    }

    type Response struct {
        Status string `json:"status"`
        Data   Data   `json:"data"`
    }
    type apiR struct {
        Response Response
    }

    var r apiR
    err := json.Unmarshal([]byte(body), &r)
    if err != nil {
        fmt.Printf("err was %v", err)
    }
    fmt.Printf("decoded is %v", r)

}

您可以在这里运行代码示例。

英文:

I'm trying to decode some json in Go but some fields don't get decoded.
See the code running in browser here:

What am I doing wrong?

I need only the MX records so I didn't define the other fields. As I understand from the godoc you don't need to define the fields you don't use/need.

// You can edit this code!
// Click here and start typing.
package main
import "fmt"
import "encoding/json"
func main() {
body := `
{"response": {
"status": "SUCCESS",
"data": {
"mxRecords": [
{
"value": "us2.mx3.mailhostbox.com.",
"ttl": 1,
"priority": 100,
"hostName": "@"
},
{
"value": "us2.mx1.mailhostbox.com.",
"ttl": 1,
"priority": 100,
"hostName": "@"
},
{
"value": "us2.mx2.mailhostbox.com.",
"ttl": 1,
"priority": 100,
"hostName": "@"
}
],
"cnameRecords": [
{
"aliasHost": "pop.a.co.uk.",
"canonicalHost": "us2.pop.mailhostbox.com."
},
{
"aliasHost": "webmail.a.co.uk.",
"canonicalHost": "us2.webmail.mailhostbox.com."
},
{
"aliasHost": "smtp.a.co.uk.",
"canonicalHost": "us2.smtp.mailhostbox.com."
},
{
"aliasHost": "imap.a.co.uk.",
"canonicalHost": "us2.imap.mailhostbox.com."
}
],
"dkimTxtRecord": {
"domainname": "20a19._domainkey.a.co.uk",
"value": "\"v=DKIM1; g=*; k=rsa; p=DkfbhO8Oyy0E1WyUWwIDAQAB\"",
"ttl": 1
},
"spfTxtRecord": {
"domainname": "a.co.uk",
"value": "\"v=spf1 redirect=_spf.mailhostbox.com\"",
"ttl": 1
},
"loginUrl": "us2.cp.mailhostbox.com"
}
}}`
type MxRecords struct {
value    string
ttl      int
priority int
hostName string
}
type Data struct {
mxRecords []MxRecords
}
type Response struct {
Status string `json:"status"`
Data   Data   `json:"data"`
}
type apiR struct {
Response Response
}
var r apiR
err := json.Unmarshal([]byte(body), &r)
if err != nil {
fmt.Printf("err was %v", err)
}
fmt.Printf("decoded is %v", r)
}

答案1

得分: 30

根据关于 json.Unmarshal 的 Go 文档,你只能解码到导出字段,主要原因是外部包(如 encoding/json)无法访问未导出的字段。

如果你的 JSON 不符合 Go 的命名约定,你可以在字段中使用 json 标签来改变 JSON 键和结构字段之间的匹配关系。

示例:

package main

import (
	"fmt"
	"encoding/json"
)

type T struct {
	Foo  string `json:"foo"`
    priv string `json:"priv"`
}

func main() {
	text := []byte(`{"foo":"bar", "priv":"nothing"}`)
	var t T
	err := json.Unmarshal(text, &t)
	if err != nil {
		panic(err)
	}
	fmt.Println(t.Foo) // 输出 "bar"
	fmt.Println(t.priv) // 输出 "",priv 未导出
}
英文:

As per the go documentaiton about json.Unmarshal, you can only decode toward exported fields, the main reason being that external packages (such as encoding/json) cannot acces unexported fields.

If your json doesn't follow the go convention for names, you can use the json tag in your fields to change the matching between json key and struct field.

Exemple:

package main
import (
"fmt"
"encoding/json"
)
type T struct {
Foo  string `json:"foo"`
priv string `json:"priv"`
}
func main() {
text := []byte(`{"foo":"bar", "priv":"nothing"}`)
var t T
err := json.Unmarshal(text, &t)
if err != nil {
panic(err)
}
fmt.Println(t.Foo) // prints "bar"
fmt.Println(t.priv) // prints "", priv is not exported
}

答案2

得分: 12

你必须将结构字段转换为大写:

type MxRecords struct {
    Value    string `json:"value"`
    Ttl      int    `json:"ttl"`
    Priority int    `json:"priority"`
    HostName string `json:"hostName"`
}

type Data struct {
    MxRecords []MxRecords `json:"mxRecords"`
}

http://play.golang.org/p/EEyiISdoaE

英文:

You must Uppercase struct fields:

type MxRecords struct {
Value    string `json:"value"`
Ttl      int    `json:"ttl"`
Priority int    `json:"priority"`
HostName string `json:"hostName"`
}
type Data struct {
MxRecords []MxRecords `json:"mxRecords"`
}

http://play.golang.org/p/EEyiISdoaE

答案3

得分: 1

encoding/json包只能解码到导出的结构体字段中。你的Data.mxRecords成员没有被导出,所以在解码时会被忽略。如果你将其重命名为大写字母开头,JSON包将会注意到它。

你需要对MxRecords类型的所有成员做同样的操作。

英文:

The encoding/json package can only decode into exported struct fields. Your Data.mxRecords member is not exported, so it is ignored when decoding. If you rename it to use a capital letter, the JSON package will notice it.

You will need to do the same thing for all the members of your MxRecords type.

huangapple
  • 本文由 发表于 2014年6月19日 14:09:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/24299818.html
匿名

发表评论

匿名网友

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

确定