-1

I have this function to parse HTTP results:

func (a *Admin) ResponseDecode(structName string, body io.Reader) (interface{}, error) {
content, err := ioutil.ReadAll(body)

if err != nil {
    return nil, err
}

switch structName {
case "[]Cat":
    var data []Cat
    err = json.Unmarshal(content, &data)

    if err != nil {
        return nil, err
    }
    return data, err

case "[]Dog":
    var data []Dog
    err = json.Unmarshal(content, &data)

    if err != nil {
        return nil, err
    }
    return data, err
default:
    log.Fatal("Can't decode " + structName)
}

return nil, nil
}

I do a type assertion after this method :

parsed, err := a.ResponseDecode("[]Cat", resp.Body)

if err != nil {
    return nil, err
}

return parsed.([]Cat), nil

but how can I do to avoid the repetition of the code :

var data []Stuff
err = json.Unmarshal(content, &data)

if err != nil {
    return nil, err
}
return data, err

Every time I add an object? Usually I would use generics, but this is Go. What's the good way to do that ?

switch
  • 460
  • 6
  • 15

2 Answers2

1

You are passing in the name of the struct, and then expecting data of that type. Instead, you can simply pass the struct:

var parsed []Cat
err := a.ResponseDecode(&parsed, resp.Body)

where:

func (a *Admin) ResponseDecode(out interface{}, body io.Reader)  error {
  content, err := ioutil.ReadAll(body)
   if err != nil {
      return nil, err  
   }
  return json.Unmarshal(content,out)
}

In fact, you can get rid of ResponseDecode function:

var parsed []Cat
err:=json.NewDecoder(body).Decode(&parsed)
Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • It should be noted that with the last method, someone might send a very big request body to crash the server. You can protect yourself against it by using [`http.MaxBytesReader`](https://godoc.org/net/http#MaxBytesReader) to set a sane maximum – xarantolus Jan 18 '20 at 00:28
0

Found what I was looking for here. This function does the job :

func (a *Admin) ResponseDecode(body io.Reader, value interface{}) (interface{}, error) {
content, err := ioutil.ReadAll(body)

if err != nil {
    return nil, err
}

err = json.Unmarshal(content, &value)

if err != nil {
    return nil, err
}

return value, nil}
switch
  • 460
  • 6
  • 15