Golang自定义解组嵌套JSON

时间:2017-10-21 22:07:06

标签: json parsing go struct

我有一个看起来像这样的JSON对象。它包含一日三餐,共计21项,因为每餐都是个人入场。

{
    "name": "MealPlan 1508620645147",
    "items": [
        {
            "day": 1,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":869953,\"imageType\":\"jpg\",\"title\":\"Cream Cheese & Fruit Breakfast Pastries\"}"
        },
        {
            "day": 1,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":537176,\"imageType\":\"jpg\",\"title\":\"Leftover Rice Casserole\"}"
        },
        {
            "day": 1,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":595927,\"imageType\":\"jpg\",\"title\":\"Spinach and Cheddar Quiche\"}"
        },
        {
            "day": 2,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":536716,\"imageType\":\"jpg\",\"title\":\"Candied Pecan Waffles\"}"
        },
        {
            "day": 2,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":893265,\"imageType\":\"jpg\",\"title\":\"Tahini Date Smoothie Bowls\"}"
        },
        {
            "day": 2,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":512880,\"imageType\":\"jpg\",\"title\":\"Grilled Caprese Salad Sandwich for #SundaySupper\"}"
        },
        {
            "day": 3,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":648647,\"imageType\":\"jpg\",\"title\":\"Jumbo Blueberry Muffins\"}"
        },
        {
            "day": 3,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":548554,\"imageType\":\"jpg\",\"title\":\"Brie, Pesto, and Sweet Pepper Grilled Cheese\"}"
        },
        {
            "day": 3,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":438024,\"imageType\":\"jpg\",\"title\":\"Mother's Manicotti\"}"
        },
        {
            "day": 4,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":681594,\"imageType\":\"jpg\",\"title\":\"Huevos Rancheros\"}"
        },
        {
            "day": 4,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":99184,\"imageType\":\"jpg\",\"title\":\"Black Bean Tacos\"}"
        },
        {
            "day": 4,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":604514,\"imageType\":\"jpg\",\"title\":\"Cheddar Scallion Dutch Baby\"}"
        },
        {
            "day": 5,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":622672,\"imageType\":\"jpg\",\"title\":\"Cinnamon-Sugar Streusel Baked French Toast\"}"
        },
        {
            "day": 5,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":636178,\"imageType\":\"jpg\",\"title\":\"Broccoli Cheddar Soup, A Panera Bread Co. Copycat\"}"
        },
        {
            "day": 5,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":452482,\"imageType\":\"jpg\",\"title\":\"Slow Cooker Macaroni and Cheese I\"}"
        },
        {
            "day": 6,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":157272,\"imageType\":\"jpg\",\"title\":\"Pomegranate-Nutella Waffles\"}"
        },
        {
            "day": 6,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":619111,\"imageType\":\"jpg\",\"title\":\"Barley, Bulgur and Vegetable Vegan Casserole\"}"
        },
        {
            "day": 6,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":510089,\"imageType\":\"jpg\",\"title\":\"Stovetop Mac and Cheese\"}"
        },
        {
            "day": 7,
            "mealPlanId": 0,
            "slot": 1,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":551869,\"imageType\":\"jpg\",\"title\":\"Berry Smoothie\"}"
        },
        {
            "day": 7,
            "mealPlanId": 0,
            "slot": 2,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":590452,\"imageType\":\"jpg\",\"title\":\"Cheesy Baked Pasta with Eggplant and Artichokes\"}"
        },
        {
            "day": 7,
            "mealPlanId": 0,
            "slot": 3,
            "position": 0,
            "type": "RECIPE",
            "value": "{\"id\":590452,\"imageType\":\"jpg\",\"title\":\"Cheesy Baked Pasta with Eggplant and Artichokes\"}"
        }
    ]
}

我想把它解组成一系列结构,每个结构可以作为早餐,午餐,晚餐。所以,我希望我的结构看起来像这样,其中ID是来自JSON的value.id字段,而Name是来自JSON的value.title字段,{{1是Breakfast的项目,午餐是slot:1的项目,slot:2Dinner的项目。

slot:3

我怎样才能在Go中实现这一目标?我最初的想法是创建一个中间type Day struct { Breakfast meal Lunch meal Dinner meal } type meal struct { ID int Name string } 来保存来自JSON的所有数据,然后使用我需要的字段创建另一个struct。如何在不使用中间人struct的情况下执行此操作?

1 个答案:

答案 0 :(得分:1)

mayo是否建议并实施了UnmarshalJSON

func (wp *WeekPlan) UnmarshalJSON(b []byte) error {
    wp.Days = make([]Day, 7)
    var f map[string]*json.RawMessage
    json.Unmarshal(b, &f)

    var v []map[string]interface{}
    json.Unmarshal(*f["items"], &v)

    for _, item := range v {

        day := int(item["day"].(float64)) - 1
        mealnumber := int(item["slot"].(float64))

        var value map[string]interface{}
        json.Unmarshal([]byte(item["value"].(string)), &value)

        fmt.Println(value)

        id := int(value["id"].(float64))
        name := value["title"].(string)

        thisMeal := Meal{ID: id, Name: name}

        var dateUpdate Day

        dateUpdate = wp.Days[day]

        switch mealnumber {
        case 1:
            dateUpdate.Breakfast = thisMeal
        case 2:
            dateUpdate.Lunch = thisMeal
        default:
            dateUpdate.Dinner = thisMeal
        }

        wp.Days[day] = dateUpdate
    }

    return nil
}


type WeekPlan struct {
    Days []Day
}


type Day struct {
    Breakfast Meal
    Lunch     Meal
    Dinner    Meal
}


type Meal struct {
    ID       int
    Name     string
    CookTime int
    Image    string
}