如何将具有相同内部结构的两个json解组为一个golang结构?

时间:2015-07-30 12:02:10

标签: json encoding go

我有两个json文件,其结构如下

{
 "cast": [
        {
            "url": "carey-mulligan",
            "name": "Carey Mulligan",
            "role": "Actress"
        },
        {
            "url": "leonardo-dicaprio",
            "name": "Leonardo DiCaprio",
            "role": "Actor"
        },
        .
        .
        .
         ]
}

{
 "movie": [
        {
            "url": "carey-mulligan",
            "name": "Carey Mulligan",
            "role": "Actress"
        },
        {
            "url": "leonardo-dicaprio",
            "name": "Leonardo DiCaprio",
            "role": "Actor"
        },
        .
        .
        .
         ]
}

你可以看到json的内部结构对于演员和电影是相同的。我想将这些json文件解组为相同的golang结构。但我无法为相同的struct元素提供两个名称标签(演员和电影)。我想要像

这样的东西
type Detail struct {
    Name string `json:"name"`
    Url  string `json:"url"`
    Role string `json:"role"`
}

type Info struct {
    Detail []Detail `json:"cast or movie"`
}

在这种情况下,细节可以解析演员和电影。

这是我目前的代码

// RIMAGE project main.go
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

const (
    website = "https://data.moviebuff.com/"
)

func main() {
    fmt.Println("Hello World!")
    content, err := ioutil.ReadFile("data/great-getsby")
    if err != nil {
        panic(err)
    }

    var info Info

    err = json.Unmarshal(content, &info)
    if err != nil {
        panic(err)
    }

    fmt.Println(info.Detail)
}

type Detail struct {
    Name string `json:"name"`
    Url  string `json:"url"`
    Role string `json:"role"`
}

type Info struct {
    Detail []Detail `json:"cast" json:"movie"
}

但它仅适用于第一个标签“cast”,如果json包含电影,则为nill。

提前致谢。

3 个答案:

答案 0 :(得分:3)

您可以使用type Info map[string][]Detail代替您的结构。 在 Go playground

上试试

或者您可以在结构中使用这两种类型,并使方法Details()返回正确的方法:

type Info struct {
    CastDetails  []Detail `json:"cast"`
    MovieDetails []Detail `json:"movie"`
}

func (i Info) Details() []Detail {
    if i.CastDetails == nil {
        return i.MovieDetails
    }
    return i.CastDetails
}

Go playground

上试试

答案 1 :(得分:0)

在struct中尝试匿名字段:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type Detail struct {
    Name string `json:"name"`
    Url  string `json:"url"`
    Role string `json:"role"`
}

type Cast struct {
    Detail []Detail `json:"cast"`
}

type Movie struct {
    Detail []Detail `json:"movie"`
}

type Info struct {
    Cast
    Movie
}

func (i *Info) getDetails() []Detail {
    if len(i.Cast.Detail) > 0 {
        return i.Cast.Detail
    }
    return i.Movie.Detail
}

func main() {
    cast, _ := ioutil.ReadFile("./cast.json")
    movie, _ := ioutil.ReadFile("./movie.json")

    var cInfo Info
    err := json.Unmarshal(cast, &cInfo)
    fmt.Printf("cast: %+v\n", &cInfo)
    fmt.Printf("err: %v\n", err)
    fmt.Printf("details: %v\n", cInfo.getDetails())

    var mInfo Info
    err = json.Unmarshal(movie, &mInfo)
    fmt.Printf("movie: %+v\n", &mInfo)
    fmt.Printf("err: %v\n", err)
    fmt.Printf("details: %v\n", mInfo.getDetails())
}

注意事项:

  • 另一个间接级别:要访问“详细信息”字段,您需要先在信息中访问“投放”或“电影”字段。
  • 更好地为“详细信息”提供访问功能(本例中为“getDetail”)

答案 2 :(得分:-1)

如果你向encoding/json挖掘得足够远,你将会到达https://github.com/golang/go/blob/master/src/encoding/json/encode.go以及以下内容:

        tag := sf.Tag.Get("json")
        if tag == "-" {
            continue
        }

所以它获得了一个json标签并继续前进。

您可以随时使用RoninDev的解决方案,并在完成后将其复制。