-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_raw_message.go
76 lines (69 loc) · 1.79 KB
/
json_raw_message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package nulls
import (
"database/sql/driver"
"encoding/json"
"fmt"
)
// JSONRawMessage holds a json.RawMessage. Keep in mind, that the JSON NULL
// value will be represented with Valid being false.
type JSONRawMessage struct {
// RawMessage is the actual json.RawMessage when Valid.
RawMessage json.RawMessage `exhaustruct:"optional"`
// Valid when no NULL-value is represented.
Valid bool
}
// NewJSONRawMessage returns a valid JSONRawMessage with the given value.
func NewJSONRawMessage(raw json.RawMessage) JSONRawMessage {
return JSONRawMessage{
RawMessage: raw,
Valid: true,
}
}
// MarshalJSON marshals the RawMessage. If not valid, a NULL-value is returned.
func (rm JSONRawMessage) MarshalJSON() ([]byte, error) {
if !rm.Valid {
return json.Marshal(nil)
}
return json.Marshal(rm.RawMessage)
}
// UnmarshalJSON as json.RawMessage or sets Valid to false if empty.
func (rm *JSONRawMessage) UnmarshalJSON(data []byte) error {
// Do NOT use regular NULL-check here.
if isNull(data) {
rm.Valid = false
rm.RawMessage = nil
return nil
}
rm.Valid = true
return json.Unmarshal(data, &rm.RawMessage)
}
// Scan to json.RawMessage value or not valid if nil.
func (rm *JSONRawMessage) Scan(src any) error {
if src == nil {
rm.Valid = false
rm.RawMessage = nil
return nil
}
rm.Valid = true
// Copy bytes.
var srcBytes []byte
switch src := src.(type) {
case []byte:
srcBytes = src
case string:
srcBytes = []byte(src)
default:
return fmt.Errorf("unsupported source value type: %T", src)
}
b := make([]byte, len(srcBytes))
copy(b, srcBytes)
rm.RawMessage = b
return nil
}
// Value returns the value for satisfying the driver.Valuer interface.
func (rm JSONRawMessage) Value() (driver.Value, error) {
if !rm.Valid {
return nil, nil
}
return []byte(rm.RawMessage), nil
}