创建用于在Go中从API读取的结构体

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

Creating struct to read from API in Go

问题

我正在做一个项目,这是我第一次使用Go语言。

该项目查询了多个API,大部分情况下我都没有问题。

作为一个PHP背景的开发者,为我的JSON响应创建Go类型定义有点不同。

我在一个Magento API上遇到了问题,它返回的JSON响应如下所示:

{
    "66937": {
        "entity_id": "66937",
        "website_id": "1",
        "email": "email@email.com",
        "group_id": "1",
        "created_at": "2017-08-11 02:09:18",
        "disable_auto_group_change": "0",
        "firstname": "Joe",
        "lastname": "Bloggs",
        "created_in": "New Zealand Store View"
    },
    "66938": {
        "entity_id": "66938",
        "website_id": "1",
        "email": "email1@email.comm",
        "group_id": "1",
        "created_at": "2017-08-11 02:16:41",
        "disable_auto_group_change": "0",
        "firstname": "Jane",
        "lastname": "Doe",
        "created_in": "New Zealand Store View"
    }
}

我一直在使用一个名为JSON-to-Go的工具来帮助我创建struct类型,但是对于这种响应风格,它看起来不太对:

type AutoGenerated struct {
    Num0 struct {
        EntityID               string `json:"entity_id"`
        WebsiteID              string `json:"website_id"`
        Email                  string `json:"email"`
        GroupID                string `json:"group_id"`
        CreatedAt              string `json:"created_at"`
        DisableAutoGroupChange string `json:"disable_auto_group_change"`
        Firstname              string `json:"firstname"`
        Lastname               string `json:"lastname"`
        CreatedIn              string `json:"created_in"`
    } `json:"0"`
    Num1 struct {
        EntityID               string `json:"entity_id"`
        WebsiteID              string `json:"website_id"`
        Email                  string `json:"email"`
        GroupID                string `json:"group_id"`
        CreatedAt              string `json:"created_at"`
        DisableAutoGroupChange string `json:"disable_auto_group_change"`
        Firstname              string `json:"firstname"`
        Lastname               string `json:"lastname"`
        CreatedIn              string `json:"created_in"`
    } `json:"1"`
}

我只对内部的JSON数据感兴趣 - 实际上与客户有关的内容。我正在循环遍历它以提取一些信息。

我该如何创建所需的struct来读取这个JSON数据?

我查看了许多文档和文章,但它们往往使用更简单的JSON响应作为示例。

英文:

I'm working on a project and it is my first time using Go.

The project queries a number of APIs and for the most part I have had no trouble getting this working.

Coming from a PHP background, creating Go type definitions for my JSON responses is a little different.

I am stuck on one API, a Magento API, that returns a JSON response like so:

{
    "66937": {
        "entity_id": "66937",
        "website_id": "1",
        "email": "email@email.com",
        "group_id": "1",
        "created_at": "2017-08-11 02:09:18",
        "disable_auto_group_change": "0",
        "firstname": "Joe",
        "lastname": "Bloggs",
        "created_in": "New Zealand Store View"
    },
    "66938": {
        "entity_id": "66938",
        "website_id": "1",
        "email": "email1@email.comm",
        "group_id": "1",
        "created_at": "2017-08-11 02:16:41",
        "disable_auto_group_change": "0",
        "firstname": "Jane",
        "lastname": "Doe",
        "created_in": "New Zealand Store View"
    }
}

I have been using a tool, JSON-to-Go, to help me create the struct types, however it doesn't look quite right for this style of response:

type AutoGenerated struct {
	Num0 struct {
		EntityID               string `json:"entity_id"`
		WebsiteID              string `json:"website_id"`
		Email                  string `json:"email"`
		GroupID                string `json:"group_id"`
		CreatedAt              string `json:"created_at"`
		DisableAutoGroupChange string `json:"disable_auto_group_change"`
		Firstname              string `json:"firstname"`
		Lastname               string `json:"lastname"`
		CreatedIn              string `json:"created_in"`
	} `json:"0"`
	Num1 struct {
		EntityID               string `json:"entity_id"`
		WebsiteID              string `json:"website_id"`
		Email                  string `json:"email"`
		GroupID                string `json:"group_id"`
		CreatedAt              string `json:"created_at"`
		DisableAutoGroupChange string `json:"disable_auto_group_change"`
		Firstname              string `json:"firstname"`
		Lastname               string `json:"lastname"`
		CreatedIn              string `json:"created_in"`
	} `json:"1"`
}

All I am interested in is the inner JSON - the stuff to actually do with the customer. I am looping over this to extract some information.

How do I create the required struct to read from this?

I have looked at any number of documents or articles but they tend to use more simple JSON responses as examples.

答案1

得分: 1

对于你的JSON结构,以下可能适合。

播放链接:https://play.golang.org/p/ygXsdYALCb

创建一个名为Infostruct,或者你喜欢的其他名称,并根据需要自定义字段名称。

type Info struct {
    EntityID               string `json:"entity_id"`
    WebsiteID              string `json:"website_id"`
    Email                  string `json:"email"`
    GroupID                string `json:"group_id"`
    CreatedAt              string `json:"created_at"`
    DisableAutoGroupChange string `json:"disable_auto_group_change"`
    Firstname              string `json:"firstname"`
    Lastname               string `json:"lastname"`
    CreatedIn              string `json:"created_in"`
}

然后创建Info结构的map并进行解组。

var result map[string]Info
if err := json.Unmarshal(jsonBytes, &result); err != nil {
    fmt.Println(err)
}
fmt.Printf("%+v", result)

编辑:

根据评论的要求,添加一个示例的for循环:

fmt.Println("访问解组后的值:")
for key, info := range result {
    fmt.Println("Key:", key)
    fmt.Printf("Complete Object: %+v\n", info)
    fmt.Println("Individual value, typical object field access:")
    fmt.Println("EntityID:", info.EntityID)
    fmt.Println("Email:", info.Email)
}
英文:

For your JSON structure following might suit well.

Play Link: https://play.golang.org/p/ygXsdYALCb

Create a struct called Info or name you prefer also customize your field names as you like.

type Info struct {
    EntityID               string `json:"entity_id"`
    WebsiteID              string `json:"website_id"`
    Email                  string `json:"email"`
    GroupID                string `json:"group_id"`
    CreatedAt              string `json:"created_at"`
    DisableAutoGroupChange string `json:"disable_auto_group_change"`
    Firstname              string `json:"firstname"`
    Lastname               string `json:"lastname"`
    CreatedIn              string `json:"created_in"`
}

And create map of Info struct and the unmarshal it.

var result map[string]Info
if err := json.Unmarshal(jsonBytes, &result); err != nil {
	fmt.Println(err)
}
fmt.Printf("%+v", result)

EDIT:

As asked in the comment, adding for example:

fmt.Println("Accessing unmarshal values:")
for key, info := range result {
	fmt.Println("Key:", key)
	fmt.Printf("Complete Object: %+v\n", info)
 	fmt.Println("Individual value, typical object field access:")
	fmt.Println("EntityID:", info.EntityID)
	fmt.Println("Email:", info.Email)
}

答案2

得分: 1

好的,以下是翻译好的内容:

首先,我不喜欢那里自动生成的结构定义。我会将其更改为以下形式:

type Customer struct {
    EntityID               string `json:"entity_id"`
    WebsiteID              string `json:"website_id"`
    Email                  string `json:"email"`
    GroupID                string `json:"group_id"`
    CreatedAt              string `json:"created_at"`
    DisableAutoGroupChange string `json:"disable_auto_group_change"`
    Firstname              string `json:"firstname"`
    Lastname               string `json:"lastname"`
    CreatedIn              string `json:"created_in"`
}

你可能想要创建一个包装类型:

type Customers map[string]Customer

这应该可以与你提供的 JSON 数据一起使用。将它们组合起来的代码如下:

customers := Customers{}
err := json.Unmarshal(jsonBytes, &customers)
英文:

Well, first, I don't like the auto-generated struct definitions there. I would change that to look like this

type Customer struct {
    EntityID               string `json:"entity_id"`
    WebsiteID              string `json:"website_id"`
    Email                  string `json:"email"`
    GroupID                string `json:"group_id"`
    CreatedAt              string `json:"created_at"`
    DisableAutoGroupChange string `json:"disable_auto_group_change"`
    Firstname              string `json:"firstname"`
    Lastname               string `json:"lastname"`
    CreatedIn              string `json:"created_in"`
}

You may want to create a wrapper type

type Customers map[string]Customer

This should work with your json that you've provided. To put this together

customers := Customers{}
err := json.Unmarshal(jsonBytes, &customers)

答案3

得分: 0

@Xibz和@jeevatkm都提供了很好的解决方案。然而,在某些情况下,并不是所有的JSON结构都可以解组成Go结构。你可能需要定义自己的解码函数。

如果你需要为特定的数据类型或结构定义自己的解码函数,你也可以尝试使用gorilla的schema包。

https://github.com/gorilla/schema

英文:

Both @Xibz and @jeevatkm provided great solutions. However, in some cases, not all JSON structures can be unmarshalled into Go structures. You may have to define your own decoding functions.

You can also try gorilla's schema package if you have to define your own decoding function for particular data type or structures.

https://github.com/gorilla/schema

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

发表评论

匿名网友

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

确定