0

I do not know how to ask, so i will ask with an example.

I have some data like that

{
..
    "velocityStatEntries":  {

    "8753":  {

        "estimated":  {"value":  23.0,"text":  "23.0"},

        "completed":  {"value":  27.0,"text":  "27.0"}
    },

    "8673":  {

        "estimated":  {"value":  54.5,"text":  "54.5"},

        "completed":  {"value":  58.5,"text":  "58.5"}
    },
    .
    .
    .

    }
..
}

I want to declare a type that takes map key to its "KEY" or any property that is given by me. Is it possible without using map iteration?

Expected output:

{...
   "velocityStatEntries": {
   {
     "key": "8753",
     "estimated":  {"value":  54.5,"text":  "54.5"},
     "completed":  {"value":  58.5,"text":  "58.5"}
   },
   {
     "key": "8673",
     "estimated":  {"value":  54.5,"text":  "54.5"},
     "completed":  {"value":  58.5,"text":  "58.5"}
   },
  }
...
}

This is what i have done

type VelocityStatEntry struct {
    Key string
    Estimated struct {
        Value float64 `json:"value"`
        Text  string  `json:"text"`
    } `json:"estimated"`
    Completed struct {
        Value float64 `json:"value"`
        Text  string  `json:"text"`
    } `json:"completed"`
}

type RapidChartResponse struct {
    ...
    VelocityStatEntries map[string]VelocityStatEntry `json:"velocityStatEntries"`
    ..
}

But it is not working. I want to take that string map key to KEY property.

Tim Lewis
  • 27,813
  • 13
  • 73
  • 102
yabadabaduhast
  • 109
  • 1
  • 6

1 Answers1

3

If the data originates from JSON then you should skip the map[string]interface{} and instead use a custom unmarshaler implemented by your desired struct that does what you want. Perhaps by utilizing a map[string]json.RawMessage. But map[string]interface{} to struct conversion is a pain, avoid it if possible.

For example:

type VelocityStatEntryList []*VelocityStatEntry

func (ls *VelocityStatEntryList) UnmarshalJSON(data []byte) error {
    var m map[string]json.RawMessage
    if err := json.Unmarshal(data, &m); err != nil {
        return err
    }
    for k, v := range m {
        e := &VelocityStatEntry{Key: k}
        if err := json.Unmarshal([]byte(v), e); err != nil {
            return err
        }
        *ls = append(*ls, e)
    }
    return nil
}

https://go.dev/play/p/VcaW_BWXRVr

mkopriva
  • 35,176
  • 4
  • 57
  • 71