我正在使用以这种方式格式化其响应的API:
{
"err": 0,
"data": **Other json structure**
}
我现在得到响应的方式是将响应放入这样的结构中:
type Response struct {
Err int `json:"err"`
Data interface{} `json:"data"`
}
然后我得到回应后就这样做了
jsonbytes, _ := json.Marshal(resp.Data)
json.Unmarshal(jsonBytes, &dataStruct)
我只是忽略此示例中的错误。
当我知道数据的外观和类型时,我在编组和拆组似乎有点怪异。
有没有我没有看到的更简单的解决方案,或者这是正常的事情?
编辑:我可能应该提到响应对象中的Data属性可以根据我正在执行的API调用而有所不同。
JSON解组器使用反射来查看要解组的类型。给定未初始化的数据interface{}
作为未编组数据的目的地,则JSON object
将被解组到JSON中map[string]interface{}
(例如,在Playground中)。
这里有一些想法。
如果知道数据类型,则可以为每种类型定义新的响应结构。例:
type FooResponse struct {
Err int `json:"err"`
Data Foo `json:"data"`
}
type Foo struct {
FooField string `json:"foofield"`
}
type BarResponse struct {
Err int `json:"err"`
Data Bar `json:"data"`
}
type Bar struct {
BarField string `json:"barfield"`
}
如果您希望使用单个Response
结构而不是每个类型一个,可以data
使用json.RawMessage
数据类型告诉JSON解组器避免对字段进行解组,直到以后。
package main
import (
"encoding/json"
"fmt"
"log"
)
type Response struct {
Err int `json:"err"`
Data json.RawMessage `json:"data"`
}
type Foo struct {
FooField string `json:"foofield"`
}
type Bar struct {
BarField string `json:"barfield"`
}
func main() {
fooRespJSON := []byte(`{"data":{"foofield":"foo value"}}`)
barRespJSON := []byte(`{"data":{"barfield":"bar value"}}`)
var (
resp Response
foo Foo
bar Bar
)
// Foo
if err := json.Unmarshal(fooRespJSON, &resp); err != nil {
log.Fatal(err)
}
if err := json.Unmarshal(resp.Data, &foo); err != nil {
log.Fatal(err)
}
fmt.Println("foo:", foo)
// Bar
if err := json.Unmarshal(barRespJSON, &resp); err != nil {
log.Fatal(err)
}
if err := json.Unmarshal(resp.Data, &bar); err != nil {
log.Fatal(err)
}
fmt.Println("bar:", bar)
}
输出:
foo: {foo value}
bar: {bar value}
https://play.golang.org/p/Y7D4uhaC4a8
@mkopriva在对该问题的评论中指出,第三个选项是interface{}
用作中介数据类型并将其预先初始化为已知数据类型。
重点放在中介这个词上-当然interface{}
最好避免绕过(Rob Pike的Go Proverbs)。这里的用例是允许使用任何数据类型而无需多个不同的Response
类型。避免暴露的方法interface{}
是完全包装响应,仅暴露数据和错误:
package main
import (
"encoding/json"
"fmt"
"log"
)
type Foo struct {
FooField string `json:"foofield"`
}
type Bar struct {
BarField string `json:"barfield"`
}
type Error struct {
Code int
}
func (e *Error) Error() string {
return fmt.Sprintf("error code %d", e.Code)
}
func unmarshalResponse(data []byte, v interface{}) error {
resp := struct {
Err int `json:"err"`
Data interface{} `json:"data"`
}{Data: v}
if err := json.Unmarshal(data, &resp); err != nil {
return err
}
if resp.Err != 0 {
return &Error{Code: resp.Err}
}
return nil
}
func main() {
fooRespJSON := []byte(`{"data":{"foofield":"foo value"}}`)
barRespJSON := []byte(`{"data":{"barfield":"bar value"}}`)
errRespJSON := []byte(`{"err": 123}`)
// Foo
var foo Foo
if err := unmarshalResponse(fooRespJSON, &foo); err != nil {
log.Fatal(err)
}
fmt.Println("foo:", foo)
// Bar
var bar Bar
if err := unmarshalResponse(barRespJSON, &bar); err != nil {
log.Fatal(err)
}
fmt.Println("bar:", bar)
// Error response
var v interface{}
if err := unmarshalResponse(errRespJSON, &v); err != nil {
log.Fatal(err)
}
}
输出:
foo: {foo value}
bar: {bar value}
2009/11/10 23:00:00 error code 123
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句