jsongobeego

How to validate the JSON message in a POST request with Beego


I'm using Beego to develop a web server.

I used beego.Controller to process the POST requests. In my case, the POST request contains a JSON:

{
    "name": "titi",
    "password": "123456"
}

Here is my code:

type TestController struct {
    beego.Controller
}

type User struct {
    Name     string `json:"name"`
    Password string `json:"password"`
}

func (c *TestController) Post() {
    var ob md.User
    var err error
    if err = json.Unmarshal(c.Ctx.Input.RequestBody, &ob); err == nil {
        logs.Debug(ob.Name)
        logs.Debug(len(ob.Name))
    } else {
        logs.Error("illegal JSON")
    }
}

This piece of code works fine. With the help of tags of the struct User, "name" is assigned to ob.Name and "password" is assigned to ob.Password.

Now, I want to test some exception cases. For example, what if the JSON request doesn't contain the keys as expected:

{
    "illegalKey1": "titi",
    "illegalKey2": "123456"
}

As you see, I'm expecting "name" and "password" but now the keys become "illegalKey1" and "illegalKey2". So I'm thinking this can cause some errors.

To my surprise, there isn't any error because err == nil is still true, and len(ob.Name) just becomes 0 now.

So is there some good method to process this case in Go/Beego?

I mean, I know that

if len(ob.Name) == 0 {
    logs.Error("illegal JSON")
}

is OK but I'm wondering if there is some kind of more beautiful code? Otherwise, if there are 10 fields in the JSON, I have to do such an if 10 times. Obviously this is not good at all.


Solution

  • To make sure that JSON does not contain unexpected fields you can use Decoder from "encoding/json" package and it's method DisallowUnknownFields. See example here https://play.golang.org/p/bif833qxytE

    Note that to json.NewDecoder takes io.Reader as an input. You can create io.Reader from []byte by using bytes.NewReader

    Another topic is making sure that JSON contains all fields that are expected (OR these fields are in certain format). The answer to how make it work with "encoding/json" package is to implement custom UnmarshalJSON for the struct, can be found here. But I would not suggest using this approach for such task, because basically this is a validation of an input and I would rather use validation packages for this not to mix responsibilities. The most common one is go-playground/validator.v9 where you should look for required tag. Validation cases are discussed here.