Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
353 views
in Technique[技术] by (71.8m points)

go - Trying to understand the type after unmarshal JSON

I have a map where I have stored different struct types and I want to retrieve them to know what type of struct I have to do the unmashal. When the value of the key is directly the struct that I need, it works. But if I use another struct, it doesn't.

type typeStruct struct {
    typeValue interface{}
}

type typeA struct {
    Value string `json:"value"`
}

var types1 map[string]typeA = map[string]typeA{
    "typeA": typeA{},
}

var types2 map[string]typeStruct = map[string]typeStruct{
    "typeA": typeStruct{typeValue: typeA{}},
}

func main() {
    jsonString := `{
        "value": "value1"
    }`

    //this behaves as expected
    resultType1 := types1["typeA"]
    fmt.Println(fmt.Sprintf("type1: %T", resultType1)) //prints: type1: main.typeA
    json.Unmarshal([]byte(jsonString), &resultType1)
    fmt.Println(fmt.Sprintf("type1: %T", resultType1)) //prints: type1: main.typeA
    fmt.Println(resultType1)                           //prints: {value1}

    //Not this, the type is map[string]interface  instead of main.typeA
    resultType2 := types2["typeA"].typeValue
    fmt.Println(fmt.Sprintf("
type2: %T", resultType2)) //prints: type2: main.typeA
    json.Unmarshal([]byte(jsonString), &resultType2)
    fmt.Println(fmt.Sprintf("type2: %T", resultType2))   //prints: type2: map[string]interface {}
    fmt.Println(resultType2)                             //prints: map[value:value1]

}

Go Playground link

Do you know what is happening? And how can I make it work properly?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The json unmarshal has no information about typeA. What it sees is interface{}

If you provide type information to json.Unmarshal then it should identified typeA.

resultType2 := types2["typeA"].typeValue
fmt.Println(fmt.Sprintf("
type2: %T", resultType2)) 
ta, ok := resultType2.(typeA)
if ok {
    json.Unmarshal([]byte(jsonString), &ta)
    fmt.Println(fmt.Sprintf("type2: %T", ta))
    fmt.Println(ta)
}

However in your entire scheme of things how this should fit is still a question. May be you need to use switch on all the types that you have to check and use them in Unmarshall


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...