2016-09-06 19:31:45 +02:00
|
|
|
package null
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql/driver"
|
2016-09-07 13:17:27 +02:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2016-09-06 19:31:45 +02:00
|
|
|
|
2016-09-07 13:33:21 +02:00
|
|
|
"gopkg.in/nullbio/null.v5/convert"
|
2016-09-06 19:31:45 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// NullJSON is a nullable byte slice.
|
|
|
|
type NullJSON struct {
|
|
|
|
JSON []byte
|
|
|
|
Valid bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// JSON is a nullable []byte.
|
|
|
|
// JSON marshals to zero if null.
|
|
|
|
// Considered null to SQL if zero.
|
|
|
|
type JSON struct {
|
|
|
|
NullJSON
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewJSON creates a new JSON
|
|
|
|
func NewJSON(b []byte, valid bool) JSON {
|
|
|
|
return JSON{
|
|
|
|
NullJSON: NullJSON{
|
|
|
|
JSON: b,
|
|
|
|
Valid: valid,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-07 14:24:10 +02:00
|
|
|
// JSONFrom creates a new JSON that will be invalid if nil.
|
2016-09-06 19:31:45 +02:00
|
|
|
func JSONFrom(b []byte) JSON {
|
2016-09-07 14:24:10 +02:00
|
|
|
return NewJSON(b, b != nil)
|
2016-09-06 19:31:45 +02:00
|
|
|
}
|
|
|
|
|
2016-09-07 14:24:10 +02:00
|
|
|
// JSONFromPtr creates a new JSON that will be invalid if nil.
|
2016-09-06 19:31:45 +02:00
|
|
|
func JSONFromPtr(b *[]byte) JSON {
|
2016-09-07 14:24:10 +02:00
|
|
|
if b == nil {
|
2016-09-06 19:31:45 +02:00
|
|
|
return NewJSON(nil, false)
|
|
|
|
}
|
|
|
|
n := NewJSON(*b, true)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
2016-09-07 13:17:27 +02:00
|
|
|
// Unmarshal will unmarshal your JSON stored in
|
|
|
|
// your JSON object and store the result in the
|
|
|
|
// value pointed to by dest.
|
|
|
|
func (j JSON) Unmarshal(dest interface{}) error {
|
|
|
|
if dest == nil {
|
|
|
|
return errors.New("destination is nil, not a valid pointer to an object")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call our implementation of
|
|
|
|
// JSON MarshalJSON through json.Marshal
|
|
|
|
// to get the value of the JSON object
|
|
|
|
res, err := json.Marshal(j)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return json.Unmarshal(res, dest)
|
|
|
|
}
|
|
|
|
|
2016-09-06 19:31:45 +02:00
|
|
|
// UnmarshalJSON implements json.Unmarshaler.
|
2016-09-07 13:17:27 +02:00
|
|
|
// If data is len 0 or nil, it will unmarshal to JSON null.
|
|
|
|
// If not, it will copy your data slice into JSON.
|
2016-09-06 19:31:45 +02:00
|
|
|
func (j *JSON) UnmarshalJSON(data []byte) error {
|
|
|
|
if data == nil || len(data) == 0 {
|
2016-09-07 13:17:27 +02:00
|
|
|
j.JSON = []byte("null")
|
2016-09-06 19:31:45 +02:00
|
|
|
} else {
|
|
|
|
j.JSON = append(j.JSON[0:0], data...)
|
|
|
|
}
|
|
|
|
|
2016-09-07 13:17:27 +02:00
|
|
|
j.Valid = true
|
|
|
|
|
2016-09-06 19:31:45 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
2016-09-07 13:17:27 +02:00
|
|
|
// It will unmarshal to nil if the text is nil or len 0.
|
2016-09-06 19:31:45 +02:00
|
|
|
func (j *JSON) UnmarshalText(text []byte) error {
|
|
|
|
if text == nil || len(text) == 0 {
|
2016-09-07 13:17:27 +02:00
|
|
|
j.JSON = nil
|
2016-09-06 19:31:45 +02:00
|
|
|
j.Valid = false
|
|
|
|
} else {
|
|
|
|
j.JSON = append(j.JSON[0:0], text...)
|
|
|
|
j.Valid = true
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-09-07 13:17:27 +02:00
|
|
|
// Marshal will marshal the passed in object,
|
|
|
|
// and store it in the JSON member on the JSON object.
|
|
|
|
func (j *JSON) Marshal(obj interface{}) error {
|
|
|
|
res, err := json.Marshal(obj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call our implementation of
|
|
|
|
// JSON UnmarshalJSON through json.Unmarshal
|
|
|
|
// to set the result to the JSON object
|
|
|
|
return json.Unmarshal(res, j)
|
|
|
|
}
|
|
|
|
|
2016-09-06 19:31:45 +02:00
|
|
|
// MarshalJSON implements json.Marshaler.
|
2016-09-07 13:17:27 +02:00
|
|
|
// It will encode null if the JSON is nil.
|
2016-09-06 19:31:45 +02:00
|
|
|
func (j JSON) MarshalJSON() ([]byte, error) {
|
2016-09-07 13:17:27 +02:00
|
|
|
if len(j.JSON) == 0 || j.JSON == nil {
|
2016-09-06 19:31:45 +02:00
|
|
|
return []byte("null"), nil
|
|
|
|
}
|
|
|
|
return j.JSON, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalText implements encoding.TextMarshaler.
|
|
|
|
// It will encode nil if the JSON is invalid.
|
|
|
|
func (j JSON) MarshalText() ([]byte, error) {
|
|
|
|
if !j.Valid {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return j.JSON, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetValid changes this JSON's value and also sets it to be non-null.
|
|
|
|
func (j *JSON) SetValid(n []byte) {
|
|
|
|
j.JSON = n
|
|
|
|
j.Valid = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ptr returns a pointer to this JSON's value, or a nil pointer if this JSON is null.
|
|
|
|
func (j JSON) Ptr() *[]byte {
|
|
|
|
if !j.Valid {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &j.JSON
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsZero returns true for null or zero JSON's, for future omitempty support (Go 1.4?)
|
|
|
|
func (j JSON) IsZero() bool {
|
|
|
|
return !j.Valid
|
|
|
|
}
|
|
|
|
|
|
|
|
// Scan implements the Scanner interface.
|
|
|
|
func (n *NullJSON) Scan(value interface{}) error {
|
|
|
|
if value == nil {
|
|
|
|
n.JSON, n.Valid = []byte{}, false
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
n.Valid = true
|
|
|
|
return convert.ConvertAssign(&n.JSON, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Value implements the driver Valuer interface.
|
|
|
|
func (n NullJSON) Value() (driver.Value, error) {
|
|
|
|
if !n.Valid {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return n.JSON, nil
|
|
|
|
}
|