我想编写一个函数,该函数接收 几种
类型的结构并从JSON解组。为此,我有另一组带有预定义签名的函数,这些函数返回struct实例,但是由于每个函数都返回不同类型的struct,因此函数签名具有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使用接口后面的具体结构来进行编组,但实际上并没有,只是将值的映射分配给所传递的接口。
为什么不使用具体的结构,有没有办法告诉它使用具体的结构类型而无需显式转换(我在设计时不知道显式类型)?
该encoding/json
包不能奇迹般地猜测你想要的结果取消封送进去,除非你告诉它什么类型。
告诉要取消的内容的一种方法是将该类型的值传递给json.Unmarshal()
函数。
不幸的是,没有其他办法。如果您传递interface{}
类型的值,则json
包实现可以自由选择其选择的类型,它将map[string]interface{}
为JSON对象和[]interface{}
JSON数组选择。记录在json.Unmarshal()
:
要将JSON解组为接口值,Unmarshal将其中之一存储在接口值中:
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
值的type
值。由于json
包不能使用它,因此它将创建一个新的选择值(地图)。
相反,您应该在中包装一个*Foo
值interface{}
,然后传递该值:
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}
问题内容: 我想用Cython包装一个包含C ++和OpenMP代码的测试项目,并通过文件与distutils一起构建它。我文件的内容如下所示: 该标志与gcc一起用于针对OpenMP进行编译和链接。但是,如果我只是调用 由于编译器是clang,因此无法识别此标志: 我尝试指定gcc失败: 如何告诉distutils使用gcc? 问题答案: 尝试使用os.environ从setup.py内部设置“
我想用Cython包装一个包含C和OpenMP代码的测试项目,并通过一个文件用distutils构建它。我的文件内容是这样的: 标志与gcc一起用于编译和链接OpenMP。然而,如果我只是调用 无法识别此标志,因为编译器为clang: 我尝试指定gcc失败: 如何告诉distutils使用gcc?
切换到 JDK8 后,清单。MF Attributes 开始返回 https://bugs.openjdk.java.net/browse/JDK-8201636 这表明这是 Oracle 在 JDK 8u151-8u172 中引入的一个错误。 我使用pom.xml和IntelliJ IDEA。指定(标签 < br > < code > JAVA _ HOME 设置为JDK10 我安装了< cod
问题内容: 这个来自json.Unmarshal docs的示例(为便于使用而不是进行了稍微修改)有效,没有错误: 工作示例的游乐场链接 但是这个经过稍微修改的示例却没有: 非工作示例的游乐场链接 它显示了这个实际上并没有帮助的模糊错误(看起来更像是一个函数调用,而不是错误的IMO): json:Unmarshal(nil * main.Animal) 这似乎是因为它是未初始化的指针。但是文档说(
我有以下类和映射器来映射它们。如何将地图结构配置为“不”使用龙目岛构建器?(不删除@Builder注释)?使用最新版本的龙目岛和地图结构时,地图结构将在使用@Builder注记时自动使用构建器。我找不到禁用它的方法,因为我需要在@AfterMapping方法中使用实例,因为构建器不会公开所有必需的方法(@SuperBuilder在此用例中是不允许的)