json.Unmarshal and required fields

2,935 views
Skip to first unread message

Christopher Gilling

unread,
Oct 23, 2014, 3:17:48 PM10/23/14
to golan...@googlegroups.com
I've been writing a number of REST endpoints lately and find that I keep wanting be able to check and make sure that the JSON I receive contains certain fields. I've read around and seen suggestions of using pointers instead of regular data members in my structs, but there are a couple of things I don't like about that. The primary being that you still have to manually check each field to see if its been set. And when using this method to Marshal JSON it is much clumsier to deal with a pointer to an int rather than an int itself when setting the values. (i.e I can't just do s.i = 42). What I keep find myself wanting is to be able to do something like this

type Request struct {
  Field int `json:"field,required"`
}

and then have json.Unmarshal return an error if that field does not exist.

Does anyone have any thoughts on why that would be a bad idea?

Thanks,
Chris

Andrew Gerrand

unread,
Oct 23, 2014, 6:26:07 PM10/23/14
to Christopher Gilling, golan...@googlegroups.com
One argument against this is you're giving the "encoding/json" package more responsibility (that of validating your application-level requirements), when right now its sole responsibility right now is the encoding and decoding of JSON data.

The "encoding/json" package uses reflection. To solve your problem, you could write some code that uses package "reflect" to inspect fields and check whether they have been populated.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brandon Rogers

unread,
Oct 23, 2014, 8:08:54 PM10/23/14
to golan...@googlegroups.com
You might consider the beego validation package (likely many others).  Used after you decode from json into the struct of course...


type Request struct {
    Field int `json:"field" valid:"Required;Range(42,45)"`
}

func (req *Request) Valid(v *validation.Validation) {

// do any further checking here to cause validation to fail

v.SetError("This failed at 43")

}

Got some good mileage out of this so far...  It also allows an optional callback after preliminary validation is done for any "last chance" checks...

Christopher Gilling

unread,
Oct 23, 2014, 8:17:36 PM10/23/14
to golan...@googlegroups.com
Looks like the kind of thing I'm looking for great.

Christopher Gilling

unread,
Oct 23, 2014, 8:19:02 PM10/23/14
to golan...@googlegroups.com, cgil...@gmail.com
Ah, from looking into reflect more I think my misunderstanding what that I didn't know that with reflection you could tell the difference between not set and zero, and therefore I assumed that the only way to do something like this is inside the encoding/json library.

Thanks for the reply

Andrew Gerrand

unread,
Oct 23, 2014, 8:23:21 PM10/23/14
to Christopher Gilling, golan...@googlegroups.com
Ah, you would still need to use a pointer field to distinguish between not set and zero.

Caleb Spare

unread,
Oct 23, 2014, 8:25:01 PM10/23/14
to Christopher Gilling, golang-nuts
On Thu, Oct 23, 2014 at 5:19 PM, Christopher Gilling <cgil...@gmail.com> wrote:
Ah, from looking into reflect more I think my misunderstanding what that I didn't know that with reflection you could tell the difference between not set and zero,

​You cannot; there is no difference.​
Reply all
Reply to author
Forward
0 new messages