如果 GO 中的外部元素不相同,如何将嵌套的 json 解组为结构
How to unmarshal nested json to a struct, if the outer element is not the same in GO
你好,我想知道是否可以将给定的 json 解组为结构
type Movie struct {
Title string
Actors []string
ID int
Length int
RelaseDate string
}
这是 json
的示例
{
"movies": [
{
"movie_title_A": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>...."
]
},
"ID": 99992,
"length": 120,
"relaseDate": "2.10.2012"
},
{
"movie_title_B": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>...."
]
},
"ID": 123124,
"length": 90,
"relaseDate": "10.10.2012"
}
]
}
如您所见,名称字段可以采用任何名称,因为它是电影的标题。有没有一种有效的方法可以将它放入上面的结构中?
任何帮助都会很好,谢谢
考虑到它的动态特性,使用地图[string]界面可能更容易,因为您将无法定义像 asd123 和 2movie23123 这样的动态键。
package main
import (
"encoding/json"
"fmt"
)
const j = `{
"movies": [
{
"asd123": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>"
]
},
"ID": 99992,
"length": 120,
"relaseDate": "2.10.2012"
},
{
"2movie23123": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>"
]
},
"ID": 123124,
"length": 90,
"relaseDate": "10.10.2012"
}
]
}`
// Movies ...
type Movies struct {
Name string
ID float64
Length float64
ReleaseDate string
Actors []interface{}
}
func main() {
data := map[string]interface{}{}
err := json.Unmarshal([]byte(j), &data)
if err != nil {
panic(err)
}
// printing it out to show you it marshaled
// b, _ := json.MarshalIndent(data, "", " ")
// fmt.Println(string(b))
//
var myMovies []Movies
for _, d := range data {
temp := Movies{}
converting := d.([]interface{})
for _, movie := range converting {
convertingMovie := movie.(map[string]interface{})
temp.Length = convertingMovie["length"].(float64)
temp.ID = convertingMovie["ID"].(float64)
temp.ReleaseDate = convertingMovie["relaseDate"].(string)
// getting rid of these keys so the for loop below doesn't iterate on them
// need the for loop cuz I don't know what the key name is
delete(convertingMovie, "length")
delete(convertingMovie, "ID")
delete(convertingMovie, "relaseDate")
for key, val := range convertingMovie {
temp.Name = key
actors := val.(map[string]interface{})
temp.Actors = actors["actors"].([]interface{})
}
}
myMovies = append(myMovies, temp)
}
b, _ := json.MarshalIndent(myMovies, "", " ")
fmt.Println(string(b))
}
上面的方法可能是更好的方法,但我提供了一个简单的示例。最好的方法是更好地组织 json 数据,以便它更好地适合结构,否则使用反射。无需更多工作,我会使用上面的 for 循环,并将其添加到对我有意义的结构中,以便它可以更轻松地访问数据。考虑上面 JSON 解析器的开始,所以现在您可以访问 json 数据,将其装入结构,然后更改周围的数据。
你好,我想知道是否可以将给定的 json 解组为结构
type Movie struct {
Title string
Actors []string
ID int
Length int
RelaseDate string
}
这是 json
的示例{
"movies": [
{
"movie_title_A": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>...."
]
},
"ID": 99992,
"length": 120,
"relaseDate": "2.10.2012"
},
{
"movie_title_B": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>...."
]
},
"ID": 123124,
"length": 90,
"relaseDate": "10.10.2012"
}
]
}
如您所见,名称字段可以采用任何名称,因为它是电影的标题。有没有一种有效的方法可以将它放入上面的结构中? 任何帮助都会很好,谢谢
考虑到它的动态特性,使用地图[string]界面可能更容易,因为您将无法定义像 asd123 和 2movie23123 这样的动态键。
package main
import (
"encoding/json"
"fmt"
)
const j = `{
"movies": [
{
"asd123": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>"
]
},
"ID": 99992,
"length": 120,
"relaseDate": "2.10.2012"
},
{
"2movie23123": {
"actors": [
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>",
"<actorID1123123>"
]
},
"ID": 123124,
"length": 90,
"relaseDate": "10.10.2012"
}
]
}`
// Movies ...
type Movies struct {
Name string
ID float64
Length float64
ReleaseDate string
Actors []interface{}
}
func main() {
data := map[string]interface{}{}
err := json.Unmarshal([]byte(j), &data)
if err != nil {
panic(err)
}
// printing it out to show you it marshaled
// b, _ := json.MarshalIndent(data, "", " ")
// fmt.Println(string(b))
//
var myMovies []Movies
for _, d := range data {
temp := Movies{}
converting := d.([]interface{})
for _, movie := range converting {
convertingMovie := movie.(map[string]interface{})
temp.Length = convertingMovie["length"].(float64)
temp.ID = convertingMovie["ID"].(float64)
temp.ReleaseDate = convertingMovie["relaseDate"].(string)
// getting rid of these keys so the for loop below doesn't iterate on them
// need the for loop cuz I don't know what the key name is
delete(convertingMovie, "length")
delete(convertingMovie, "ID")
delete(convertingMovie, "relaseDate")
for key, val := range convertingMovie {
temp.Name = key
actors := val.(map[string]interface{})
temp.Actors = actors["actors"].([]interface{})
}
}
myMovies = append(myMovies, temp)
}
b, _ := json.MarshalIndent(myMovies, "", " ")
fmt.Println(string(b))
}
上面的方法可能是更好的方法,但我提供了一个简单的示例。最好的方法是更好地组织 json 数据,以便它更好地适合结构,否则使用反射。无需更多工作,我会使用上面的 for 循环,并将其添加到对我有意义的结构中,以便它可以更轻松地访问数据。考虑上面 JSON 解析器的开始,所以现在您可以访问 json 数据,将其装入结构,然后更改周围的数据。