如何解组带有嵌套结构的普通 JSON 数据?

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

How to umarshall plain JSON with nested struct

问题

GO新手问题。我这里有一个简单的JSON负载,我试图使用嵌套结构进行解组:

负载:

{
    "name": "foo-bar",
    "profileName": "my-profile-name"
}

和结构体:

type Project struct {
    Name    string   `json:"name"`
    Profile *Profile `json:"profileName,omitempty"`
}

type Profile struct {
    // Name is the name of the namespace created for the project
    Name string `json:"profileName"`
}

经过多次尝试和错误,我找到了一个可行的解决方案

package main

import (
    "encoding/json"
    "fmt"
)

type Project struct {
    Name    string   `json:"name"`
    Profile *Profile `json:"profileName,omitempty"`
}

type Profile struct {
    // Name is the name of the namespace created for the project
    Name string `json:"profileName"`
}

func (p *Profile) UnmarshalJSON(data []byte) error {
    // 首先尝试解组为字符串
    var s string
    err := json.Unmarshal(data, &s)
    if err == nil {
        p.Name = s
        return nil
    }

    // 否则解组为结构体
    type Alias Profile
    aux := &struct {
        *Alias
    }{
        Alias: (*Alias)(p),
    }
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    *p = *(*Profile)(aux.Alias)
    return nil
}

func main() {
    payload := []byte(`{
        "name": "foo-bar",
        "profileName": "my-profile-name"
    }`)

    project := Project{
        Profile: &Profile{},
    }
    err := json.Unmarshal(payload, &project)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Name: %s\nProfile Name: %s", project.Name, project.Profile.Name)
}

但是这看起来有点繁琐和冗长。有没有更好的方法来做到这一点?谢谢

英文:

GO newbie question. I have a simple JSON payload here, which I'm trying to unmarshall with a nested struct:

The payload:

{
    "name": "foo-bar",
    "profileName": "my-profile-name"
}

and the structs:

type Project struct {
	Name    string   `json:"name"`
	Profile *Profile `json:"profileName,omitempty"`
}

type Profile struct {
	// Name is the name of the namespace created for the project
	Name string `json:"profileName"`
}

After a lot of trials and errors I landed on the solution that works

package main

import (
	"encoding/json"
	"fmt"
)

type Project struct {
	Name    string   `json:"name"`
	Profile *Profile `json:"profileName,omitempty"`
}

type Profile struct {
	// Name is the name of the namespace created for the project
	Name string `json:"profileName"`
}

func (p *Profile) UnmarshalJSON(data []byte) error {
	// try to unmarshal as a string first
	var s string
	err := json.Unmarshal(data, &s)
	if err == nil {
		p.Name = s
		return nil
	}

	// otherwise unmarshal as a struct
	type Alias Profile
	aux := &struct {
		*Alias
	}{
		Alias: (*Alias)(p),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	*p = *(*Profile)(aux.Alias)
	return nil
}

func main() {
	payload := []byte(`{
		"name": "foo-bar",
		"profileName": "my-profile-name"
	}`)

	project := Project{
		Profile: &Profile{},
	}
	err := json.Unmarshal(payload, &project)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Name: %s\nProfile Name: %s", project.Name, project.Profile.Name)
}

but this just looks a little too cumbersome and verbose. Is there a better way to do this? Thanks

答案1

得分: 1

你可以按照以下方式进行操作:

type Profile struct {
	Name string `json:"profileName"`
}

func (p *Profile) UnmarshalJSON(data []byte) error {
	if len(data) == 4 && string(data) == "null" { // null?
		return nil
	} else if data[0] == '"' { // string?
		return json.Unmarshal(data, &p.Name)
	} else if data[0] == '{' { // object?
		type P Profile
		return json.Unmarshal(data, (*P)(p))
	}
	return nil // 或者返回错误
}

https://go.dev/play/p/-rOhbmWvmWs

英文:

You can do the following:

type Profile struct {
	Name string `json:"profileName"`
}

func (p *Profile) UnmarshalJSON(data []byte) error {
	if len(data) == 4 && string(data) == "null" { // null?
		return nil
	} else if data[0] == '"' { // string?
		return json.Unmarshal(data, &p.Name)
	} else if data[0] == '{' { // object?
		type P Profile
		return json.Unmarshal(data, (*P)(p))
	}
	return nil // or return error
}

https://go.dev/play/p/-rOhbmWvmWs

huangapple
  • 本文由 发表于 2023年3月11日 23:24:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75705933.html
匿名

发表评论

匿名网友

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

确定