繁体   English   中英

解码 Go 中的动态字段

[英]Decoding a dynamic field in Go

我收到来自外部 API 的响应,该字段的字段可以有 2 个值:

{"field": []}

或者

{"field": {"key1": "value", "key2": "value"}}

我将结构设置为

type Object Struct {
   Field map[string]string `json:"field,omitempty"`
}

然后调用我自己实现的 function 来解码响应

func decode(response *http.Response) (*Object, error) {
    var response Object
    err := json.NewDecoder(response.Body).Decode(&response)
    if err != nil {
        return nil, err
    }

    return &response, nil
}

但这仅适用于第二个响应(当字段不为空时)。 对于第一个响应,我得到一个错误。

重命名decode function 中的变量response 由于声明的 function 参数和变量同名,因此会造成混淆。

您可以为Field执行自定义封送拆收器类型。 例子:

type keys struct {
        Key1 string
        Key2 string
}

type mytype struct {
        EmptySlice bool
        Keys       *keys
}

func (m *mytype) UnmarshalJSON(b []byte) error {
        if bytes.Equal(b, []byte("[]")) {
                m.EmptySlice = true
                return nil
        }

        m.Keys = &keys{}
        return json.Unmarshal(b, &m.Keys)
}

type Object struct {
        Field mytype `json:"field"`
}

func main() {
        input := []string{
                `{"field": []}`,
                `{"field": {"key1": "value", "key2": "value"}}`,
        }

        for i, s := range input {
                var o Object

                err := json.Unmarshal([]byte(s), &o)
                if err != nil {
                        log.Fatal(err)
                }

                fmt.Printf("%d: %+v\n", i+1, o)
        }
}

https://go.dev/play/p/OqSKfUXHFyb

您可以使用自定义类型并在该类型上实现 UnmarshalJSON 接口方法。

例如:

type Field struct {
    arr []string
    m   map[string]string
}

func (f *Field) UnmarshalJSON(b []byte) error {
    var m map[string]string
    err := json.Unmarshal(b, &m)
    if err == nil {
        f.m = m
        return nil
    }

    var arr []string
    err = json.Unmarshal(b, &arr)
    if err == nil {
        f.arr = arr
        return nil
    }

    return fmt.Errorf("type of property not array or map")
}

https://go.dev/play/p/JuFE--hWAjw

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM