0

I have an API that is expecting a "username":"string" request body, I am unmarshalling the request body into a user struct that matches what I am expecting. My code does not throw an error on mismatched struct data. Is there a function I could use instead of json.Unmarshal? If not how would I be able to catch a 400 error in this case? (I have also tried using json.decoder)

Here is my code:

type User struct {
   Username string `json:"username" gorm:"primary_key;Column:username"`
}

var user models.User

body, err := ioutil.ReadAll(r.Body)
if err = json.Unmarshal(body, &user); err != nil {
    http.Error(w, err.Error(), http.StatusBadRequest)
    return
}
dmc94
  • 536
  • 1
  • 5
  • 16

2 Answers2

2

You can use the DisallowUnknownFields option of json.Decoder to cause an error when the decoder finds a field that is not in the struct:

DisallowUnknownFields causes the Decoder to return an error when the destination is a struct and the input contains object keys which do not match any non-ignored, exported fields in the destination.

xarantolus
  • 1,961
  • 1
  • 11
  • 19
0

If you want to both ensure that the key "username" is present, and that other fields are not, you would need to implement the Unmarshaler interface, and iterate over all of the received keys.

func (user *User) UnmarshalJSON(data []byte) (error) {                                                    
    d := make(map[string]interface{})                                                                                                    
    err = json.Unmarshal(data, &d)                                                                         
    if err != nil {                                                                                               
        return err
    }
    if _, ok := d["username"]; !ok {
        return fmt.Errorf("username is required")
    }
    for k, v := range d {
        if k == "username" {
            username, ok := v.(string)
            if !ok {
                return fmt.Errorf("username must be a string, got %T", v)
            }
            user.Username = username
        } else {
            return fmt.Errorf("Unexpected key %s", k)
        }
    }
    return                                                                                                  
}       
dave
  • 62,300
  • 5
  • 72
  • 93