试图找到一个简单的解决方案,将封送/解压缩到以下结构中
type Resource struct {
Data []ResourceData `json:"data"`
}
type ResourceData struct {
Id string `json:"id"`
Type string `json:"type"`
Attributes map[string]interface{} `json:"attributes"`
Relationships map[string]Resource `json:"relationships"`
}
r := Resource{}
json.Unmarshal(body, &r)
如果:
body = `{"data":[{"id":"1","type":"blah"}]}`
然而,我也需要它对以下问题作出回应:
body = `{"data":{"id":"1","type":"blah"}}` //notice no slice
我可以做一个单独的类型
type ResourceSingle struct {
Data ResourceData `json:"data"`
}
但是,这意味着需要复制我附加到资源的所有功能,这是可能的。但是,在执行它之前,我需要找出要解封送回的类型,另外,当涉及到关系部分时,每个类型都可能包含数据:[]{}或数据{},这样这个想法就行不通了。
或者我可以用
map[string]*json.RawMessage
//or
type Resource struct {
Data *json.RawMessage `json:"data"`
}
但是,在json表单中,我如何知道它是一个片还是一个节点来提供要解编组的正确结构呢?
我的最后一招是将umarshal放入映射接口,并使用大量的反射测试。但这是一个很长的喘息期。
想法?
好样的,jJ
发布于 2015-11-06 15:30:33
有很多方法来构造它,但是最简单的技术就是实现json.Unmarshaler
,并检查数据的类型。您可以最小限度地解析json字节,通常只是第一个字符,或者您可以尝试将其解封为每个类型并返回成功的类型。
我们将在这里使用后一种技术,并将ResourceData插入到片中,而不管传入数据的格式如何,因此我们始终可以以相同的方式对其进行操作:
type Resource struct {
Data []ResourceData
}
func (r *Resource) UnmarshalJSON(b []byte) error {
// this gives us a temporary location to unmarshal into
m := struct {
DataSlice struct {
Data []ResourceData `json:"data"`
}
DataStruct struct {
Data ResourceData `json:"data"`
}
}{}
// try to unmarshal the data with a slice
err := json.Unmarshal(b, &m.DataSlice)
if err == nil {
log.Println("got slice")
r.Data = m.DataSlice.Data
return nil
} else if err, ok := err.(*json.UnmarshalTypeError); !ok {
// something besides a type error occurred
return err
}
// try to unmarshal the data with a struct
err = json.Unmarshal(b, &m.DataStruct)
if err != nil {
return err
}
log.Println("got struct")
r.Data = append(r.Data, m.DataStruct.Data)
return nil
}
http://play.golang.org/p/YIPeYv4AfT
https://stackoverflow.com/questions/33569210
复制相似问题