json - 如何将嵌套的 JSON 解析为 Go 中的结构?

标签 json go struct unmarshalling

我怎样才能像这样将嵌套的 JSON 映射到嵌套的结构:

type ChildStruct1 struct {
    key3,
    key4,string
}
type ChildStruct2 struct {
    key4,
    key5,string
}

type MainStruct struct {
    key1,
    key2,string
    childStruct1 ChildStruct1
    childStruct2 ChildStruct1
}

输入JSON:

{
  key1: val1,
  key2: val2,
  chilDStruct1 : {
                     key3: val3,
                     key4: val4,
                }
  chilDStruct2 : {
                     key5: val5,
                     key6: val6,
                }
}

如何映射。我在 Java 中使用过 jsonMapper 但不知道如何在这里使用。我试过了,但这不起作用:

var data MainStruct
    file, err := ioutil.ReadFile("jsonData.json")
    if err != nil {
        log.Fatal(err)
    }
    err = json.Unmarshal(file, &data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(data.key1)

我也试过这个:

u := &MainStruct{}
file, err := ioutil.ReadFile("jsonData.json")
if err != nil {
    log.Fatal(err)
}
err = json.Unmarshal([]byte(file), u)
if err != nil {
    log.Fatal(err)
}
fmt.Println(u.key1)

但输出总是0

最佳答案

您的示例中有很多错误(在 JSON 文本和源代码中)。让我们修复它们。

JSON 文本

首先,您的 JSON 无效。试试这个而不是你的:

{
    "key1": "val1",
    "key2": "val2",
    "childStruct1" : {
        "key3": "val3",
        "key4": "val4"
    },
    "childStruct2" : {
        "key5": "val5",
        "key6": "val6"
    }
}

Go 类型定义

其次,您定义结构类型的 Go 源代码存在语法错误。

第三,您必须按顺序导出结构字段,以便 json 包可以设置它们的值。试试这个而不是你的:

type ChildStruct1 struct {
    Key3 string
    Key4 string
}

type ChildStruct2 struct {
    Key4 string
    Key5 string
}

type MainStruct struct {
    Key1         string
    Key2         string
    ChildStruct1 ChildStruct1
    ChildStruct2 ChildStruct2
}

解析JSON文本的代码

现在介绍解析 JSON 文本的代码。您可以使用 ioutil.ReadFile() 将整个文件读入内存,但通常不读取整个文件而是将其“流”到解码器(使用文件作为输入)会更有效。

os.Open()返回 *File .它不是 []byte,但它实现了 io.Reader .所以你不能把它传递给 json.Unmarshal() .而是创建一个 json.Decoder使用 json.NewDecoder()它接受 io.Reader,因此您可以传递打开的文件。并且不要忘记使用 File.Close() 关闭打开的文件, 最好将其作为延迟语句关闭(如果打开成功)。

f, err := os.Open("jsonData.json")
if err != nil {
    log.Panic(err)
}
defer f.Close()

var data MainStruct
err = json.NewDecoder(f).Decode(&data)
if err != nil {
    log.Panic(err)
}
fmt.Println(data.Key1)
fmt.Printf("%+v", data)

(请注意,我使用了 log.Panic() 而不是 log.Fatal(),因为后者调用了 os.Exit(),因此我们的延迟函数不会被调用。)

输出:

val1
{Key1:val1 Key2:val2 ChildStruct1:{Key3:val3 Key4:val4} ChildStruct2:{Key4: Key5:val5}}

Go Playground 的修改版本

这是一个修改版本,它从源代码中定义的常量解析 JSON 文本,在 Go Playground 上试试:

var data MainStruct
err := json.Unmarshal([]byte(input), &data)
if err != nil {
    log.Fatal(err)
}
fmt.Println(data.Key1)
fmt.Printf("%+v", data)

最后的笔记

JSON 文本中的键以小写字母开头,Go 中的结构字段名称以大写字母开头(需要导出),但是 json 包“聪明”到足以匹配它们.如果你使用不同的东西,你可以使用 tags指定如何在 json 中找到结构字段,例如

type ChildStruct1 struct {
    Key3 string `json:"myKey3"`
    Key4 string `json:"myKey4"`
}

关于json - 如何将嵌套的 JSON 解析为 Go 中的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34015049/

相关文章:

java - 无法使用自定义反序列化器反序列化 JSON 对象

json - 什么是 JSONSerialized URLRequest 的复杂键对值的正确 Swift 3 数据类型

go - 如何将 Golang 项目(一组包)放到 Github?

go - 在Go中比较结构

c# - 如何将数字从文本框转换为 int 数组?

json - Swift:如何将接收到的字符串转换为 json

json - 在带有 Jmespath 的多选哈希中使用来自 json src 文档的键

c++ - 如何防止静态类成员变量需要两个定义/声明?

go - 获取 syslog.Writer undefined

C fwrite() 不会保存文件中的所有数据