2

Gin's request validation feature is not working when the request body (JSON) represents an array of objects

Ex:

[ 
   { 
      "field1":"aaa",
      "field2":"bbb"
   }
]

code:

type item struct {
    Field1 string `json:"field1" binding:"required"`
    Field2 string `json:"field2" binding:"required"`
}

var items []item

err := c.BindJSON(&items)

To be more clear, the validation logic in gin is expecting the root object to be a struct and hence bails out when an array type gets passed.

what is best way to validate each object in an array passed in the body?

Peggy
  • 372
  • 1
  • 6
  • 27

1 Answers1

1

The JSON will be parsed here and then validated here.

The comment on the default ValidateStruct method:

ValidateStruct receives any kind of type, but only performed struct or pointer to struct type.

You can work around this by defining a struct, as it is needed, that holds your data:

type itemHolder struct {
    Items []item
}

Then defining a custom Unmarshaler, like this:

func (i *itemHolder) UnmarshalJSON(b []byte) error {
    return json.Unmarshal(b, &i.Items)
}

Now *itemHolder implements json.Unmarshaler, which means in turn that it will be a struct that is supported by gin.

This code should work now:

var items itemHolder

err := c.BindJSON(&items)
if err != nil {
    // handle...
}

// use items.Items from here on

Please note that your marshal behaviour will change; so you should definitely implement the Marshaler interface if you need to.

xarantolus
  • 1,961
  • 1
  • 11
  • 19