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

因为我经常 unmarshal http.Response.Body,所以我想我可以编写一个函数来处理读取、关闭和解组到各种不同结构中的所有麻烦。这就是为什么我引入了一个函数func unmarhalInterface(closer *io.ReadCloser, v *interface{}) error,然后可以使用 断言返回值t:=i.(T)

我已经将它包装成类型的值*interface{},但是因为覆盖类型是interface{}而不是myStructjson所以包实现选择了map[string]interface{}。之后类型断言就会失败(当然)。我是否缺少任何内容或需要此实现“手动”进行类型断言,这意味着查找映射中的所有字段并将我想要的字段分配到我的结构中。

下面的代码有最少的示例,注释中带有注释。如果我的解释不够充分,请离开。

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 = 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

}


扬帆大鱼
浏览 144回答 1
1回答

蛊毒传说

空接口不是实际类型,它基本上是匹配任何内容的东西。正如评论中所述,指向空接口的指针实际上没有意义,因为指针已经与空接口匹配,因为所有内容都与空接口匹配。为了让你的代码正常工作,你应该删除结构周围的接口包装器,因为这只会扰乱 json 类型检查,而空接口的全部意义在于你可以向它传递任何内容。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 = &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 interfacesfunc 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)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go