如果外部元素在GO中不相同,如何将嵌套的json解组为结构

时间:2017-03-28 18:21:45

标签: json go unmarshalling

嗨,我想知道是否有可能将这个给定的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"
    }
]
}

正如您所看到的,Name字段可以采用任何名称,因为它是电影的标题。有没有一种有效的方法将它放入上面的结构中? 任何帮助都会很好,谢谢

1 个答案:

答案 0 :(得分:0)

鉴于它的动态特性,使用map [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数据,将其放入结构中,然后更改数据。