Golang json根据键值对解组

I have json as following

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

and the structs are as follows:

type universeTypeData struct {
Recent       universeSearchInfo 
Popular      universeSearchInfo 
Digital      universeSearchInfo 
}

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

I want to unmarshal my json as "id" with value "recent_search" map to Recent, "id" with value "popular_search" map to Popular. Is there any way of doing this in golang?

My approach of doing it is

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

Is there any better way of doing it?

Implement Unmarshaler interface:

Unmarshaler is the interface implemented by types that can unmarshal a JSON description of themselves. The input can be assumed to be a valid encoding of a JSON value. UnmarshalJSON must copy the JSON data if it wishes to retain the data after returning.

json unmarshaler interface assign the value from json to struct after parsing the result and applying conditions to fetch the value.

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
}

Working code on Go Playground

You want to unmurshal JSON array into Go struct which is not natural mapping. Any way, you most likely should be first unmurshal in slice and then parse this slice. Some workaround is to use 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()

which allow you to decode on the fly, in one pass, without consuming intermediate slice representation. Working example