gpt4 book ai didi

json - 如何告诉 json.Unmarshal 使用结构而不是接口(interface)

转载 作者:IT王子 更新时间:2023-10-29 01:01:35 33 4
gpt4 key购买 nike

我想编写一个函数来接收几种 类型的结构并从 JSON 中解码它们。为此,我有另一组函数具有返回结构实例的预定义签名,但由于每个函数返回不同类型的结构,函数签名将 interface{} 作为返回类型。

当我发送 json.Unmarshal 一个具体结构时,它按我预期的方式工作,但是当我发送与 interface{} 相同的结构时,它会将其转换为一个映射。

这是描述问题的简化示例代码:

package main

import (
"encoding/json"
"fmt"
)

type Foo struct {
Bar string `json:"bar"`
}

func getFoo() interface{} {
return Foo{"bar"}
}

func main() {

fooInterface := getFoo()
fooStruct := Foo{"bar"}
fmt.Println(fooInterface) //{bar}
fmt.Println(fooStruct) //{bar}

myJSON := `{"bar":"This is the new value of bar"}`
jsonBytes := []byte(myJSON)

err := json.Unmarshal(jsonBytes, &fooInterface )
if err != nil {
fmt.Println(err)
}
fmt.Println(fooInterface) //map[bar:This is the new value of bar]

err = json.Unmarshal(jsonBytes, &fooStruct)
if err != nil {
fmt.Println(err)
}
fmt.Println(fooStruct) //{This is the new value of bar}
}

https://play.golang.org/p/tOO7Ki_i4c

我希望 json.Unmarshal 使用接口(interface)后面的具体结构进行解码,但它没有,只是将值映射分配给传递的接口(interface)。

为什么它不使用具体结构并且有没有办法告诉它使用具体结构类型而无需显式转换(我在设计时不知道显式类型)?

最佳答案

encoding/json除非您告诉它,否则包无法神奇地猜出您希望将结果解码为哪种类型。

告诉解码成什么的一种方法是将该类型的值传递给 json.Unmarshal() 函数。

不幸的是,没有其他办法。如果您传递 interface{} 类型的值,json 包实现可以自由选择它所选择的类型,它会选择 map[string] interface{} 用于 JSON 对象,[]interface{} 用于 JSON 数组。这记录在 json.Unmarshal() :

To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null

如果您事先知道类型,请创建该类型的值,并将其传递给解码。您是否事先将其存储在 interface{} 变量中并不重要;如果传递的值适合解码,它将被使用。请注意,如果传递的值不是该类型,则将包装在 interface{} 中,因为这是 json.Unmarshal() 的参数类型。

您的代码失败的问题是因为您传递了一个 *interface{} 类型的值,它包装了一个非指针 Foo 值。由于 json 包不能使用它,它会创建一个它选择的新值( map )。

相反,您应该在 interface{} 中包装一个 *Foo 值,然后传递它:

func getFoo() interface{} {
return &Foo{"bar"}
}

func main() {
fooInterface := getFoo()

myJSON := `{"bar":"This is the new value of bar"}`
jsonBytes := []byte(myJSON)

err := json.Unmarshal(jsonBytes, fooInterface)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%T %+v", fooInterface, fooInterface)
}

结果(在 Go Playground 上尝试):

*main.Foo &{Bar:This is the new value of bar}

关于json - 如何告诉 json.Unmarshal 使用结构而不是接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44779319/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com