为了账号安全,请及时绑定邮箱和手机立即绑定

json.Unmarshal 接口指针以及稍后的类型断言

json.Unmarshal 接口指针以及稍后的类型断言

Go
扬帆大鱼 2023-06-26 16:48:31
因为我经常 unmarshal http.Response.Body,所以我想我可以编写一个函数来处理读取、关闭和解组到各种不同结构中的所有麻烦。这就是为什么我引入了一个函数func unmarhalInterface(closer *io.ReadCloser, v *interface{}) error,然后可以使用 断言返回值t:=i.(T)。我已经将它包装成类型的值*interface{},但是因为覆盖类型是interface{}而不是myStruct,json所以包实现选择了map[string]interface{}。之后类型断言就会失败(当然)。我是否缺少任何内容或需要此实现“手动”进行类型断言,这意味着查找映射中的所有字段并将我想要的字段分配到我的结构中。下面的代码有最少的示例,注释中带有注释。如果我的解释不够充分,请离开。package mainimport (    "bytes"    "encoding/json"    "fmt"    "io"    "io/ioutil"    "log")type myStruct struct {    A string `json:"a"`    B string `json:"b"`}func main() {    jsonBlob := []byte(`{"a":"test","b":"test2"}`)    var foo = interface{}(myStruct{})    closer := ioutil.NopCloser(bytes.NewReader(jsonBlob))    err := unmarshalCloser(&closer, &foo)    if err != nil {        log.Fatal(err)    }    fmt.Println(fmt.Sprintf("%v", foo))    // That´s what i want:    foo2 := foo.(myStruct)    fmt.Println(foo2.A)}func unmarshalCloser(closer *io.ReadCloser, v *interface{}) error {    defer func() { _ = (*closer).Close() }()    data, err := ioutil.ReadAll(*closer)    if err != nil {        return err    }    err = json.Unmarshal(data, v)    if err != nil {        return err    }    return nil}
查看完整描述

1 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

空接口不是实际类型,它基本上是匹配任何内容的东西。正如评论中所述,指向空接口的指针实际上没有意义,因为指针已经与空接口匹配,因为所有内容都与空接口匹配。为了让你的代码正常工作,你应该删除结构周围的接口包装器,因为这只会扰乱 json 类型检查,而空接口的全部意义在于你可以向它传递任何内容。


package main


import (

    "bytes"

    "encoding/json"

    "fmt"

    "io"

    "io/ioutil"

    "log"

)


type myStruct struct {

    A string `json:"a"`

    B string `json:"b"`

}


func main() {

    jsonBlob := []byte(`{"a":"test","b":"test2"}`)


    var foo = &myStruct{} // This need to be a pointer so its attributes can be assigned

    closer := ioutil.NopCloser(bytes.NewReader(jsonBlob))


    err := unmarshalCloser(closer, foo)

    if err != nil {

        log.Fatal(err)

    }

    fmt.Println(fmt.Sprintf("%v", foo))


    // That´s what i want:

    fmt.Println(foo.A)

}


// You don't need to declare either of these arguments as pointers since they're both interfaces

func unmarshalCloser(closer io.ReadCloser, v interface{}) error {

    defer closer.Close()

    // v NEEDS to be a pointer or the json stuff will barf


    // Simplified with the decoder

    return json.NewDecoder(closer).Decode(v)

}


查看完整回答
反对 回复 2023-06-26
  • 1 回答
  • 0 关注
  • 97 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信