I am trying to figure out how one can properly marhsall nullable type (string, int, time) properly to JSON in Go. I know that database/sql
provide sql.NullTime
, sql.NullInt
, etc but when you marshall these values, you get something like
{"first_name": {
"Value": "",
"Valid": false,
}}
What I really want is
{"first_name": null}
I understand that you can implement your own MarshalJSON to do this (I wrote about it here http://dennissuratna.com/marshalling-nullable-string-db-value-to-json-in-go/)
BUT I am wondering if anyone knows a better way to do this. I want to know other people know a less tedious way to do this.
Create a type that embeds (e.g.) sql.NullInt and implements the json.Marshaler interface.
If you really want to have null field, you will have to resort to a custom marshaller (or maybe, just maybe, use *string
fields in struct and assign nil
instead of an empty string).
However, if you look at the original goal of JSON (JavaScript Object Notation), you will notice that in JavaScript there is hardly any difference between:
var obj = JSON.parse('{"first_name": null }');
alert(obj.first_name)
and:
var obj = JSON.parse('{}');
alert(obj.first_name)
In other words: assigning null
to a field has the same effect as not specifying it all. And most JSON parsers work like this.
Not specifying empty fields is supported by the Go JSON marshaller:
type MyType struct {
firstname string `json:omitempty`
}
In the end, it depends on what you want to do with your JSON :)
May be late, but when searching for the same problem google report this page at a high rank, so : my solution is to define special type that surcharge NullInt64 for exemple and has and export JSON
Example for NullInt64 :
// NullInt64 is the same as sql.NullInt64
// But when exported to JSON it is null or the int64 val that is exported
// not a JSON containing Value and Valid properties
type NullInt64 struct {
sql.NullInt64
}
// NullInt64 MarshalJSON interface redefinition
func (r NullInt64) MarshalJSON() ([]byte, error) {
if r.Valid {
return json.Marshal(r.Int64)
} else {
return json.Marshal(nil)
}
}
And then replace all sql.NullInt64 by NullInt64. You can easily do the same for sql.NullString. Hope it helps