在不同的JSON映射中解码结构体

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

Decoding structs in different JSON mappings

问题

我正在尝试解码具有相同属性但来自不同JSON映射的两个不同响应,唯一的区别是它们的名称。

如何正确实现下面的示例?

type ResponseProperties struct {
    CurrentPage uint
    TotalPages  uint
    Events      []TrackingEvent
}

type TrackingResponse struct {
    // ResponseProperties
    CurrentPage uint            `json:"current_page"`
    TotalPages  uint            `json:"total_pages"`
    Events      []TrackingEvent `json:"clicks"`
}

type SubscriberResponse struct {
    // ResponseProperties
    CurrentPage uint            `json:"current_page"`
    TotalPages  uint            `json:"total_pages"`
    Events      []TrackingEvent `json:"subscribers"`
}
英文:

I am trying to decode two different responses with the same properties, the only difference is the names of the JSON mappings they come from.

What is the proper way to achieve the demonstrated below?

type ResponseProperties struct {
	CurrentPage uint
	TotalPages  uint
	Events      []TrackingEvent
}

type TrackingResponse struct {
	//	ResponseProperties
	CurrentPage uint            `json:"current_page"`
	TotalPages  uint            `json:"total_pages"`
	Events      []TrackingEvent `json:"clicks"`
}

type SubscriberResponse struct {
	//	ResponseProperties
	CurrentPage uint            `json:"current_page"`
	TotalPages  uint            `json:"total_pages"`
	Events      []TrackingEvent `json:"subscribers"`
}

答案1

得分: 3

我建议将它们分开保持独立。你永远不知道API响应何时会突然改变。

但是,如果你确实想将所有内容解组为一个结构体,一种方法是解组为一个具有所有可能别名字段的结构体,然后分配非空的字段。例如:

type Basket struct {
    NumFruit int
    Fruits   []string // 在JSON中可以是"Apples"或"Oranges"。
}

func (bskt *Basket) UnmarshalJSON(b []byte) error {
    type Basket_ Basket
    v := struct {
        Basket_
        Apples, Oranges []string
    }{}
    if err := json.Unmarshal(b, &v); err != nil {
        return err
    }
    *bskt = Basket(v.Basket_)
    if v.Apples != nil {
        bskt.Fruits = v.Apples
    }
    if v.Oranges != nil {
        bskt.Fruits = v.Oranges
    }
    return nil
}

Playground: http://play.golang.org/p/pLe5EwsYEP

英文:

I'd suggest just keeping them separate. You never know when an API response suddenly changes.

But if you do want to unmarshal everything into one struct, one way to do this is to unmarshal into a struct that has fields for all possible aliases and then assign the one that is not empty. E.g.:

type Basket struct {
	NumFruit int
	Fruits   []string // Can be either "Apples" or "Oranges" in JSON.
}

func (bskt *Basket) UnmarshalJSON(b []byte) error {
	type Basket_ Basket
	v := struct {
		Basket_
		Apples, Oranges []string
	}{}
	if err := json.Unmarshal(b, &v); err != nil {
		return err
	}
	*bskt = Basket(v.Basket_)
	if v.Apples != nil {
		bskt.Fruits = v.Apples
	}
	if v.Oranges != nil {
		bskt.Fruits = v.Oranges
	}
	return nil
}

Playground: http://play.golang.org/p/pLe5EwsYEP.

答案2

得分: 0

你可以通过在另一个结构体中嵌入一个ResponseProperties指针,并在这些结构体中实现json.Unmarshaller接口,来覆盖unmarshal行为。请注意结构体内指针的危险,因为指针默认为nil。

这里有一个playground的示例:http://play.golang.org/p/ZTlLp0_wGY

英文:

You can override the unmarshal behavior by embedding a ResponseProperties pointer in another struct and implementing the json.Unmarshaller interface in those structs. Be aware the dangers of pointers inside structs, since pointers will default to nil.

Here's a playground example: http://play.golang.org/p/ZTlLp0_wGY

huangapple
  • 本文由 发表于 2016年1月26日 22:04:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/35015666.html
匿名

发表评论

匿名网友

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

确定