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

huangapple go评论82阅读模式
英文:

How to parse nested JSON into structs in Go?

问题

如何将嵌套的JSON映射到嵌套的结构体中?你可以尝试以下方法:

首先,你需要定义相应的结构体类型来映射JSON数据。根据你提供的代码,你可以这样定义结构体:

type ChildStruct1 struct {
    Key3 string `json:"key3"`
    Key4 string `json:"key4"`
}

type ChildStruct2 struct {
    Key4 string `json:"key4"`
    Key5 string `json:"key5"`
}

type MainStruct struct {
    Key1          string       `json:"key1"`
    Key2          string       `json:"key2"`
    ChildStruct1  ChildStruct1 `json:"childStruct1"`
    ChildStruct2  ChildStruct2 `json:"childStruct2"`
}

然后,你可以使用json.Unmarshal函数将JSON数据解析到结构体中。你可以尝试以下代码:

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)

确保你的JSON文件路径正确,并且JSON数据的键名与结构体字段的标签匹配。

希望这可以帮助到你!如果你有其他问题,请随时提问。

英文:

How can I map a nested JSON to a nested Struct like this:

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

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

Input 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. 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.

答案1

得分: 3

你的示例中有一些错误(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.NewDecoder()创建一个json.Decoder,它接受一个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"`
}
英文:

You have quite some errors in your example (both in JSON text and source code). Let's fix them.

JSON text

First your JSON is not valid. 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.

Third, you have to export struct fields in order so the json package can set their values. 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

And now on to the code to parse the JSON text. 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).

os.Open() returns a *File. It is not a []byte, but it implements io.Reader. So you can't pass it to json.Unmarshal(). Instead create a json.Decoder using json.NewDecoder() which accepts an io.Reader, so you can pass the opened file. And don't forget to close the opened file using File.Close(), best to close it as a deferred statement (if opening it succeeds).

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.)

Output:

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

Modified version for the 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:

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. Should you use something different, you could use tags to specify how a struct field can be found in the json, e.g.

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

huangapple
  • 本文由 发表于 2015年12月1日 15:41:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/34015049.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定