英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论