如何在 Go 中使用不同的 json 标签将 json 从一个结构编组到另一个结构?
How to Marshall json from one struct to another with different json tags in Go?
我正在创建一个 Go 应用程序,它使用来自多个来源的数据,这些来源都具有相似的数据,但结构与其 data/responses 不同。这些响应需要编组到一个通用结构中,然后发送到另一个服务。
常用结构:
type common struct {
ID string `json:id`
GivenName string `json:given_name`
FamilyName string `json:family_name`
Email: string `json:email`
}
一个回复:
{
"id": "123",
"first_name": "john",
"last_name": "smith",
"email": "js@mail.com"
}
另一个回复:
{
"id": "456",
"first": "larry",
"last": "smith",
"email": {
"primary": "larry@mail.com"
}
}
如何将具有一种结构的 json 响应编组为具有不同结构的结构?
我觉得你可以根据不同的来源定义不同的结构。然后,把它转化成那个普通的结构。
当添加新源时,此方法灵活、可读且易于实施。
示例代码如下:
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID string `json:id`
GiveName string `json:given_name`
FamilyName string `json:family_name`
Email string `json:email`
}
type UserFromMySQL struct {
ID string `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
}
func (u *UserFromMySQL) GetUser() *User {
return &User{
ID: u.ID,
GiveName: u.FirstName,
FamilyName: u.LastName,
Email: u.Email,
}
}
func main() {
um := new(UserFromMySQL)
b := []byte(`{
"id": "123",
"first_name": "john",
"last_name": "smith",
"email": "js@mail.com"
}`)
err := json.Unmarshal(b, um)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", um)
fmt.Printf("%+v\n", um.GetUser())
}
当然可以通过增加冗余字段来实现,定义user
如下:
type Email {
Primary string `json:"primary"`
}
type User struct {
ID string `json:"id"`
GiveName string `json:"given_name"`
FamilyName string `json:"family_name"`
FirstName string `json:"last_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
}
选择适合你的方式。我更喜欢第一个。
我建议您为您拥有的每个数据分离结构。
Golang 是一种强类型语言,所以每个结构体应该只代表一种数据类型。这不仅消除了 Guam 代码,还减少了其他开发人员需要跟踪一种数据类型的时间,这有时会发生在 Python 等非强类型语言中。
无论如何,如果你真的需要在同一个结构中表示这些数据,你可以像下面这样写。
type User struct {
ID string `json:"id,omitempty"`
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
FirstName string `json:"first,omitempty"`
LastName string `json:"last,omitempty"`
PlainEmail string `json:"plain_email,omitempty"`
Email struct{
Primary string `json:"primary"`
} `json:"email,omitempty"`
}
在JSON标签中添加omitempty,所以如果结构是用用户类型A创建的,那么类型B的字段将不会在[=28=中表示].但是,我不推荐这种方法,但如果需要,可以采用这种方法。
无论如何,Email 和 PlainEmail JSON 标签需要分开,否则编译器会混淆。
我正在创建一个 Go 应用程序,它使用来自多个来源的数据,这些来源都具有相似的数据,但结构与其 data/responses 不同。这些响应需要编组到一个通用结构中,然后发送到另一个服务。
常用结构:
type common struct {
ID string `json:id`
GivenName string `json:given_name`
FamilyName string `json:family_name`
Email: string `json:email`
}
一个回复:
{
"id": "123",
"first_name": "john",
"last_name": "smith",
"email": "js@mail.com"
}
另一个回复:
{
"id": "456",
"first": "larry",
"last": "smith",
"email": {
"primary": "larry@mail.com"
}
}
如何将具有一种结构的 json 响应编组为具有不同结构的结构?
我觉得你可以根据不同的来源定义不同的结构。然后,把它转化成那个普通的结构。
当添加新源时,此方法灵活、可读且易于实施。
示例代码如下:
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID string `json:id`
GiveName string `json:given_name`
FamilyName string `json:family_name`
Email string `json:email`
}
type UserFromMySQL struct {
ID string `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
}
func (u *UserFromMySQL) GetUser() *User {
return &User{
ID: u.ID,
GiveName: u.FirstName,
FamilyName: u.LastName,
Email: u.Email,
}
}
func main() {
um := new(UserFromMySQL)
b := []byte(`{
"id": "123",
"first_name": "john",
"last_name": "smith",
"email": "js@mail.com"
}`)
err := json.Unmarshal(b, um)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", um)
fmt.Printf("%+v\n", um.GetUser())
}
当然可以通过增加冗余字段来实现,定义user
如下:
type Email {
Primary string `json:"primary"`
}
type User struct {
ID string `json:"id"`
GiveName string `json:"given_name"`
FamilyName string `json:"family_name"`
FirstName string `json:"last_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
}
选择适合你的方式。我更喜欢第一个。
我建议您为您拥有的每个数据分离结构。
Golang 是一种强类型语言,所以每个结构体应该只代表一种数据类型。这不仅消除了 Guam 代码,还减少了其他开发人员需要跟踪一种数据类型的时间,这有时会发生在 Python 等非强类型语言中。
无论如何,如果你真的需要在同一个结构中表示这些数据,你可以像下面这样写。
type User struct {
ID string `json:"id,omitempty"`
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
FirstName string `json:"first,omitempty"`
LastName string `json:"last,omitempty"`
PlainEmail string `json:"plain_email,omitempty"`
Email struct{
Primary string `json:"primary"`
} `json:"email,omitempty"`
}
在JSON标签中添加omitempty,所以如果结构是用用户类型A创建的,那么类型B的字段将不会在[=28=中表示].但是,我不推荐这种方法,但如果需要,可以采用这种方法。
无论如何,Email 和 PlainEmail JSON 标签需要分开,否则编译器会混淆。