-
Notifications
You must be signed in to change notification settings - Fork 1
/
json.go
132 lines (114 loc) · 2.92 KB
/
json.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package notnull
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"io"
)
// JSON is a []byte slice containing JSON text.
// JSON(nil) is interpreted as an empty json object: {}
// Implements the interfaces:
// json.Marshaler, json.Unmarshaler, driver.Value, sql.Scanner.
// Use nullable.JSON if the JSON(nil) value should be
// interpreted as JSON "null" and SQL "NULL".
type JSON []byte
func MarshalJSON(source any) (JSON, error) {
return json.Marshal(source)
}
// MarshalFrom marshalles source as JSON and sets it
// at j when there was no error.
func (j *JSON) MarshalFrom(source any) error {
jsonBytes, err := json.Marshal(source)
if err == nil {
*j = jsonBytes
}
return err
}
// UnmarshalTo unmashalles the JSON of j to dest
func (j JSON) UnmarshalTo(dest any) error {
if j == nil {
return json.Unmarshal([]byte("{}"), dest)
}
return json.Unmarshal(j, dest)
}
// MarshalJSON returns j as the JSON encoding of j.
// MarshalJSON implements encoding/json.Marshaler
// See the package function MarshalJSON to marshal
// a struct into JSON
func (j JSON) MarshalJSON() ([]byte, error) {
if j == nil {
return []byte("{}"), nil
}
return j, nil
}
// UnmarshalJSON sets *j to a copy of sourceJSON.
// UnarshalJSON implements encoding/json.Unmarshaler
// See method Unmarshal for unmarshalling into a struct.
func (j *JSON) UnmarshalJSON(sourceJSON []byte) error {
if j == nil {
return errors.New("UnmarshalJSON on nil pointer")
}
// Use append trick to make a copy of sourceJSON
*j = append(JSON(nil), sourceJSON...)
return nil
}
// Valid reports whether j is a valid JSON encoding.
func (j JSON) Valid() bool {
if j == nil {
return false
}
return json.Valid(j)
}
// Value returns j as a SQL value.
func (j JSON) Value() (driver.Value, error) {
if j == nil {
return []byte("{}"), nil
}
return []byte(j), nil
}
// IsEmpty returns true if j is nil, or an empty JSON value like "", "{}", or "[]"
func (j JSON) IsEmpty() bool {
switch string(j) {
case "", "{}", "[]":
return true
}
return false
}
// Scan stores the src in *j. No validation is done.
func (j *JSON) Scan(src any) error {
switch x := src.(type) {
case nil:
*j = JSON("{}") // should we do this, set nil or error?
case string:
// Converting from string does a copy
*j = JSON(x)
case []byte:
// Need to copy because, src will be gone after call.
// Use append trick to make a copy of src bytes
*j = append(JSON(nil), x...)
default:
return errors.New("Incompatible type for JSON")
}
return nil
}
// String returns the JSON as string.
// String implements the fmt.Stringer interface.
func (j JSON) String() string {
if j == nil {
return "{}"
}
return string(j)
}
func (j JSON) GoString() string {
return fmt.Sprintf("notnull.JSON(`%s`)", j)
}
func (j JSON) PrettyPrint(w io.Writer) {
fmt.Fprintf(w, "`%s`", j)
}
// Clone returns a copy of j
func (j JSON) Clone() JSON {
clone := make(JSON, len(j))
copy(clone, j)
return clone
}