简体   繁体   English

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

[英]How to parse nested JSON into structs in Go?

How can I map a nested JSON to a nested Struct like this: 我如何像这样将嵌套的JSON映射到嵌套的Struct:

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

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

Input JSON: 输入JSON:

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

How can this be mapped. 如何映射。 I have used jsonMapper in Java but not sure how to do it here. 我已经在Java中使用了jsonMapper,但不确定在这里如何做。 I tried this but this is not working: 我尝试了这个,但这不起作用:

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)

I tried this also: 我也尝试过这个:

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)

But output is always 0 . 但是输出始终为0

You have quite some errors in your example (both in JSON text and source code). 您的示例中有很多错误(JSON文本和源代码)。 Let's fix them. 让我们修复它们。

JSON text JSON文字

First your JSON is not valid. 首先,您的JSON无效。 Try this instead of yours: 试试这个代替你的:

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

Go type definitions 转到类型定义

Second, your Go source defining your struct types has syntax errors. 其次,定义结构类型的Go源代码存在语法错误。

Third, you have to export struct fields in order so the json package can set their values. 第三,您必须按顺序导出struct字段,以便json包可以设置其值。 Try this instead of yours: 试试这个代替你的:

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
}

Code to parse the JSON text 解析JSON文本的代码

And now on to the code to parse the JSON text. 现在继续分析JSON文本的代码。 You can read the whole file into memory using ioutil.ReadFile() , but often it is more efficient to not read the whole file but to "stream" it to a decoder (using the file as the input). 您可以使用ioutil.ReadFile()将整个文件读入内存,但是通常不读取整个文件,而是将其“流”送到解码器(使用文件作为输入)会更有效。

os.Open() returns a *File . os.Open()返回一个*File It is not a []byte , but it implements io.Reader . 它不是[]byte ,但是实现了io.Reader So you can't pass it to json.Unmarshal() . 因此,您不能将其传递给json.Unmarshal() Instead create a json.Decoder using json.NewDecoder() which accepts an io.Reader , so you can pass the opened file. 相反,创建一个json.Decoder使用json.NewDecoder()它接受一个io.Reader ,这样你就可以通过打开的文件。 And don't forget to close the opened file using File.Close() , best to close it as a deferred statement (if opening it succeeds). 并且不要忘记使用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)

(Note that I used log.Panic() instead of log.Fatal() as the latter calls os.Exit() and hence our deferred function would not be called.) (请注意,我使用log.Panic()代替log.Fatal()因为后者调用os.Exit() ,因此不会调用我们的延迟函数。)

Output: 输出:

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

Modified version for the Go Playground Go Playground的修改版本

Here is a modified version that parses the JSON text from a constant defined in the source code, try it on the 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)

Final notes 最后的笔记

Keys in the JSON text start with lowercase letters, struct field names in Go start with uppercase letters (needed in order to be exported), but the json package is "clever" enough to match them. JSON文本中的键以小写字母开头,Go中的结构字段名称以大写字母开头(为了导出需要),但是json包足够“聪明”以匹配它们。 Should you use something different, you could use tags to specify how a struct field can be found in the json, eg 如果您使用其他内容,则可以使用标签来指定如何在json中找到struct字段,例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM