Golang json根据键值对解组

时间:2018-07-16 09:39:10

标签: json go unmarshalling

我有以下json

"data": [
    {
        "id": "recent_search",
        "items": [],
        "name": ""
    },
    {
        "id": "popular_search",
        "items": [],
        "name": ""
    },
    {
        "id": "digital",
        "items": [],
        "name": "DIGITAL"
    }
]

,其结构如下:

type universeTypeData struct {
Recent       universeSearchInfo 
Popular      universeSearchInfo 
Digital      universeSearchInfo 
}

type universeSearchInfo struct {
ID    string               `json:"id"`
Name  string               `json:"name"`
Items []universeSearchItem `json:"items"`
}

我想解封我的json为“ id”,值“ recent_search”映射到“最近”,“ id”,值“ popular_search”映射为Popular。在golang中有什么办法吗?

我这样做的方法是

for _, v := range result.Data {
    if v.ID == "in_category" {
        finalResult.Universe.InCategory.ID = v.ID
        finalResult.Universe.InCategory.Name = v.Name
        for _, abc := range v.Items {
            finalResult.Universe.InCategory.Items = append(finalResult.Universe.InCategory.Items, abc)
        }
    }
    if v.ID == "recent_search" {
        finalResult.Universe.Recent.ID = v.ID
        finalResult.Universe.Recent.Name = v.Name
        for _, abc := range v.Items {
            finalResult.Universe.Recent.Items = append(finalResult.Universe.Recent.Items, abc)
        }
    }
    if v.ID == "popular_search" {
        finalResult.Universe.Popular.ID = v.ID
        finalResult.Universe.Popular.Name = v.Name
        for _, abc := range v.Items {
            finalResult.Universe.Popular.Items = append(finalResult.Universe.Popular.Items, abc)
        }
    }

还有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

您想将JSON数组解组到非自然映射的Go结构中。无论如何,您最有可能首先应该在切片中保持不打扰,然后再对此切片进行解析。一些解决方法是使用json.Decoder

dec := json.NewDecoder(JSONdataReader)
var res universeTypeData
// read open bracket
dec.Token()
// while the array contains values
for dec.More() {
    var m universeSearchInfo
    // decode an array value
    dec.Decode(&m)
    switch m.ID {
    case "recent_search":
        res.Recent = m
    case "popular_search":
        res.Popular = m
    case "digital":
        res.Digital = m
    }
}
// read closing bracket
dec.Token()

,可让您一次完成动态解码,而无需消耗中间片段表示。 Working example

答案 1 :(得分:0)

实施Unmarshaler界面:

  

Unmarshaler是由可以解组一个   自己的JSON描述。输入可以假定为有效   JSON值的编码。 UnmarshalJSON必须复制JSON数据(如果有)   希望在返回后保留数据。

json unmarshaler接口在解析结果并应用条件以获取值之后,将json中的值分配给struct。

package main

import (
    "encoding/json"
    "fmt"
)

type Details struct {
    Data []universeSearchInfo `json:"data"`
}

type universeTypeData struct {
    Recent  universeSearchInfo
    Popular universeSearchInfo
    Digital universeSearchInfo
}

type universeSearchInfo struct {
    ID    string   `json:"id"`
    Name  string   `json:"name"`
    Items []string `json:"items"`
}

func main() {
    var result universeTypeData
    jsonBytes := []byte(`{"data": [
                    {
                        "id": "recent_search",
                        "items": [],
                        "name": ""
                    },
                    {
                        "id": "popular_search",
                        "items": [],
                        "name": ""
                    },
                    {
                        "id": "digital",
                        "items": [],
                        "name": "DIGITAL"
                    }
                ]}`)
    if err := json.Unmarshal(jsonBytes, &result); err != nil {
        fmt.Println(err)
    }
    fmt.Println(result)

}

func (universeData *universeTypeData) UnmarshalJSON(data []byte) error {
    var result Details
    if err := json.Unmarshal(data, &result); err != nil {
        return err
    }
    for _,value := range result.Data{
        switch value.ID {
            case "recent_search":
                universeData.Recent = value
        }
    }
    return nil
}

Go Playground上工作的代码