jsongoencoding-json-go

Is it possible to have a structure for dynamic keys along with static keys for json in Golang


My apologies for the basic question. I am new to Golang and I have the json to parse as below

{
   "config1":{
      "Parameters":{
         "Pm1":"value",
         "Pm2":"value",
         "Pm3":"value"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value",
            "b":"value",
            "c":"value",
            "d":"value"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}

I am trying to write a struct to parse this json and wrote the struct in the following way.

type Parameters struct {
    Pm1 string `json:"Pm1"`
    Pm2 string `json:"Pm2"`
    Pm3 string `json:"Pm3"`
}

type dynamicParametes struct {
    a string `json:"a"`
    b string `json:"b"`
    c string `json:"c"`
    d string `json:"d"`
}

type dynamic struct {
    Parameters dynamicParametes `json:"Parameters"`
    Epoch      string           `json:"Epoch"`
}

type config1 struct {
    Parameters   Parameters         `json:"Parameters"`
    Dynamic_keys map[string]dynamic `json:"-"`
    Epoch        string             `json:"Epoch"`
}

type config struct {
    config1 config1 `json:"config1"`
}

I was hoping that the map will match all the matching keys with dynamic structs and show them in the map. But, I see it created an empty map in the response.


Solution

  • Implemented custom unmarshler for config type.

    Note

    type config struct {
        Config1 config1 `json:"config1"`
    }
    
    type _config config
    
    func (b *config) UnmarshalJSON(data []byte) error {
    
        var v = struct {
            Config1 map[string]interface{} `json:"config1"`
        }{}
        if err := json.Unmarshal(data, &v); err != nil {
            return err
        }
    
        c := _config{}
        err := json.Unmarshal(data, &c)
        if err != nil {
            return err
        }
        
        b.Config1.Parameters = c.Config1.Parameters
        b.Config1.Epoch = c.Config1.Epoch
    
        if b.Config1.Dynamic_keys == nil {
            b.Config1.Dynamic_keys = map[string]dynamic{}
        }
    
        for key, config := range v.Config1 {
            if key == `Parameters` || key == `Epoch` {
                continue
            }
            data, err := json.Marshal(config)
            if err != nil {
                return err
            }
    
            d := dynamic{}
            err = json.Unmarshal(data, &d)
            if err != nil {
                return err
            }
            b.Config1.Dynamic_keys[key] = d
        }
    
        return nil
    }
    

    you can see full code here