diff --git a/pkg/sqlutil/json.go b/pkg/sqlutil/json.go new file mode 100644 index 000000000..44b4dcb71 --- /dev/null +++ b/pkg/sqlutil/json.go @@ -0,0 +1,58 @@ +package sqlutil + +import ( + "database/sql/driver" + "encoding/json" + "fmt" +) + +// JSON defined JSON data type, need to implements driver.Valuer, sql.Scanner interface +type JSON json.RawMessage + +// Value return json value, implement driver.Valuer interface +func (j JSON) Value() (driver.Value, error) { + if len(j) == 0 { + return nil, nil + } + bytes, err := json.RawMessage(j).MarshalJSON() + return string(bytes), err +} + +// Scan scan value into Jsonb, implements sql.Scanner interface +func (j *JSON) Scan(value interface{}) error { + if value == nil { + *j = JSON("null") + return nil + } + var bytes []byte + switch v := value.(type) { + case []byte: + bytes = v + case string: + bytes = []byte(v) + default: + return fmt.Errorf("Failed to unmarshal JSONB value: %+v", value) + } + + result := json.RawMessage{} + err := json.Unmarshal(bytes, &result) + *j = JSON(result) + return err +} + +// MarshalJSON to output non base64 encoded []byte +func (j JSON) MarshalJSON() ([]byte, error) { + return json.RawMessage(j).MarshalJSON() +} + +// UnmarshalJSON to deserialize []byte +func (j *JSON) UnmarshalJSON(b []byte) error { + result := json.RawMessage{} + err := result.UnmarshalJSON(b) + *j = JSON(result) + return err +} + +func (j JSON) String() string { + return string(j) +}