这很好,如果:
body =`{data:[{id:1,type:blah}]}`不过,我也需要回应:
body =`{data:{id:1,type:blah}}`//注意没有切片我可以创建一个单独的类型
类型ResourceSingle struct { Data ResourceData`json:data`}然而,这意味着需要复制我已附加到资源的所有功能,这是可能的。但是,我需要在执行之前找出解开哪种类型,再加上关系部分,每个部分都可以包含数据:[] {}或data {},这样这个想法就不会出现工作。
或者我可以使用
map [string] * json.RawMessage //或类型资源结构{ Data * json.RawMessage`json:data`}但是,如果以json的形式表达,我怎么知道它是一个片段还是一个节点来提供正确的解构结构?
我最后的手段是将umarshal放入map [string]接口并使用大量的反射测试..但是这是非常长的时间。
想法?
亲切的问候,jJ
解决方案有很多方法来构造它,但最简单的技术归结为实现 json.Unmarshaler ,并检查数据的类型。您可以最小化解析json字节,通常只是第一个字符,或者您可以尝试解组到每个类型并返回成功。
我们将使用后一种技术,并将ResourceData插入切片,而不管输入数据的格式如何,所以我们可以始终以相同的方式对它进行操作:
类型资源结构{ Data [] ResourceData } func(r * Resource)UnmarshalJSON(b []字节)错误{ //这给了我们一个临时的位置以解密为m:= struct { DataSlice struct { Data [] ResourceData`json:data`} DataStruct struct { Data ResourceData`json:data`} } {} //尝试用片段解组数据 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 { //除了发生类型错误之外的其他东西 return err } //尝试使用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 }play.golang/p/YIPeYv4AfT
Trying to find a simple solution to marshaling/unmashaling into the following struct
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)this is great if:
body = `{"data":[{"id":"1","type":"blah"}]}`However I also need it to respond to:
body = `{"data":{"id":"1","type":"blah"}}` //notice no sliceI could make a separate type
type ResourceSingle struct { Data ResourceData `json:"data"` }However, that would mean needing to duplicate all the functions I have attached to resource, which is possible. However, i would need to find out which type to unmarshal into before executing it, plus when it comes to the relationships part, each of those could contain data:[]{} or data{}, so that idea isn't going to work.
Alternatively I could use
map[string]*json.RawMessage //or type Resource struct { Data *json.RawMessage `json:"data"` }but still, when in json form how do I know if it is a slice or a node to supply the correct struct to unmarshal into?
My last resort is to umarshal into map[string]interface and use lots of reflect testing .. but this is very long winded.
Ideas?
Kind regards, jJ
解决方案There's a number of ways to structure it, but the simplest technique comes down to implementing a json.Unmarshaler, and inspecting the type of the data. You can minimally parse the json bytes, often just the first character, or you can try to unmarshal into each type and return the one that succeeds.
We'll use the latter technique here, and insert the ResourceData into a slice regardless of the incoming data's format, so we can always operate on it in the same manner:
type Resource struct { Data []ResourceData } func (r *Resource) UnmarshalJSON(b []byte) error { // this gives us a temporary location to unamrshal 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 unamrshal 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 }play.golang/p/YIPeYv4AfT
更多推荐
去json unmarshal选项
发布评论