How to dynamically assign objects to a string key in slices in Go?

Viewed 4145

I am trying to create an array from already created array. Array that I have is

{
  "id": 1,
  "category": "fruits",
  "name": "Apple",
  "description": "Apple is my favorite fruit."
}

{
  "id": 2,
  "category": "colors",
  "name": "Red",
  "description": "Red color is always charming."
}

{
  "id": 3,
  "category": "flowers",
  "name": "Lotus",
  "description": "It is one of the most beautiful flowers in this world."
}

{
  "id": 4,
  "category": "colors",
  "name": "Pink",
  "description": "A romantic color, mostly liked by women."
}
{
  "id": 5,
  "category": "flowers",
  "name": "Rose",
  "description": "I love roses."
}

{
  "id": 6,
  "category": "fruits",
  "name": "Mango",
  "description": "Mango is one of my favorite fruits."
}

Now I need to create an array and populate data like:

"elements":{
   "fruits":{
      0:{
         "id": 1,
         "category": "fruits",
         "name": "Apple",
         "description": "Apple is my favorite fruit."
       }
     1:{
        "id": 6,
        "category": "fruits",
        "name": "Mango",
        "description": "Mango is one of my favorite fruits."
       }
     }
    "flowers":{
        0:{
            "id": 3,
            "category": "flowers",
            "name": "Lotus",
            "description": "It is one of the most beautiful flowers in this world."
         }
        1:{
          "id": 5,
          "category": "flowers",
          "name": "Rose",
          "description": "I love roses."
        }
      }
    "colors":{
       0:{
          "id": 2,
          "category": "colors",
          "name": "Red",
          "description": "Red color is always charming."
        }
      1:{
        "id": 4,
        "category": "colors",
        "name": "Pink",
        "description": "A romantic color, mostly liked by women."
       } 
    }
}

What I have tried is:

    arr             := make(map[string]interface{})
    arrCate         := make(map[string]interface{})
    arrCateFlower   := make(map[int]interface{})
    arrCateColor    := make(map[int]interface{})
    arrCateFruit    := make(map[int]interface{})

    for index, data := range dataVals{
        if(data.Category == "flower"){
            arrCateFlower[index] = data
        }
        if(data.Category == "colors"){
            arrCateColor[index] = data  
        }
        if(data.Category == "fruits"){
            arrCateFruit[index] = data  
        }
    }
    arrCate["flowers"] = arrCateFlower
    arrCate["colors"] = arrCateColor
    arrCate["fruits"] = arrCateFruit
    arr["elements"] = arrCate

Where dataVals contain the unformatted data given at the top. By applying the above code I am able to get the proper output. But I don't think it is efficient way. If I try something like

    arr             := make(map[string]interface{})
    arrCate         := make(map[string]interface{})

    for _, data := range dataVals{
      arrCate[data.Category] = data    
    }
    arr["elements"] = arrCate

Then I get something like:

"elements":{
   "fruits":{
              "id": 6,
              "category": "fruits",
              "name": "Mango",
              "description": "Mango is one of my favorite fruits."
            }
    "flowers":{
               "id": 5,
               "category": "flowers",
               "name": "Rose",
               "description": "I love roses."
              }
    "colors":{
               "id": 4,
               "category": "colors",
               "name": "Pink",
               "description": "A romantic color, mostly liked by women." 
             }
}

the last elements of that particular category in the loop. I don't understand how can I get all the elements in the array without using any static values in code.

I have already spent hours in this. Can anyone please tell what am i missing in it?

2 Answers
// If atributes names equals , set value to fields
// target receive values of object
func Assign(target interface{}, object interface{}) {
    t := reflect.ValueOf(target).Elem()
    o := reflect.ValueOf(object).Elem()
    for i := 0; i < o.NumField(); i++ {
        for j := 0; j < t.NumField(); j++ {
            if o.Type().Field(i).Name == t.Type().Field(j).Name {
                t.Field(j).Set(o.Field(i))
            }
        }
    }
}
// Use this exemple objects interfaces diffrents but fields are equals
// Assign(&target, &object)
Related