簡體   English   中英

json.Unmarshal 接口指針,帶有稍后的類型斷言

[英]json.Unmarshal interface pointer with later type assertion

因為我經常解組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
}

Golang游樂場

空接口不是實際類型,它基本上是匹配任何東西的東西。 正如評論中所述,指向空接口的指針實際上沒有意義,因為指針已經與空接口匹配,因為一切都與空接口匹配。 為了使您的代碼工作,您應該刪除結構周圍的接口包裝器,因為這只會搞亂 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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM