...
1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "encoding/json"
6 "errors"
7 "fmt"
8 "reflect"
9 )
10
11 type JSON struct {
12 Bytes []byte
13 Status Status
14 }
15
16 func (dst *JSON) Set(src interface{}) error {
17 if src == nil {
18 *dst = JSON{Status: Null}
19 return nil
20 }
21
22 if value, ok := src.(interface{ Get() interface{} }); ok {
23 value2 := value.Get()
24 if value2 != value {
25 return dst.Set(value2)
26 }
27 }
28
29 switch value := src.(type) {
30 case string:
31 *dst = JSON{Bytes: []byte(value), Status: Present}
32 case *string:
33 if value == nil {
34 *dst = JSON{Status: Null}
35 } else {
36 *dst = JSON{Bytes: []byte(*value), Status: Present}
37 }
38 case []byte:
39 if value == nil {
40 *dst = JSON{Status: Null}
41 } else {
42 *dst = JSON{Bytes: value, Status: Present}
43 }
44
45
46
47 case JSON:
48 return errors.New("use pointer to pgtype.JSON instead of value")
49
50 case JSONB:
51 return errors.New("use pointer to pgtype.JSONB instead of value")
52
53 default:
54 buf, err := json.Marshal(value)
55 if err != nil {
56 return err
57 }
58 *dst = JSON{Bytes: buf, Status: Present}
59 }
60
61 return nil
62 }
63
64 func (dst JSON) Get() interface{} {
65 switch dst.Status {
66 case Present:
67 var i interface{}
68 err := json.Unmarshal(dst.Bytes, &i)
69 if err != nil {
70 return dst
71 }
72 return i
73 case Null:
74 return nil
75 default:
76 return dst.Status
77 }
78 }
79
80 func (src *JSON) AssignTo(dst interface{}) error {
81 switch v := dst.(type) {
82 case *string:
83 if src.Status == Present {
84 *v = string(src.Bytes)
85 } else {
86 return fmt.Errorf("cannot assign non-present status to %T", dst)
87 }
88 case **string:
89 if src.Status == Present {
90 s := string(src.Bytes)
91 *v = &s
92 return nil
93 } else {
94 *v = nil
95 return nil
96 }
97 case *[]byte:
98 if src.Status != Present {
99 *v = nil
100 } else {
101 buf := make([]byte, len(src.Bytes))
102 copy(buf, src.Bytes)
103 *v = buf
104 }
105 default:
106 data := src.Bytes
107 if data == nil || src.Status != Present {
108 data = []byte("null")
109 }
110
111 p := reflect.ValueOf(dst).Elem()
112 p.Set(reflect.Zero(p.Type()))
113
114 return json.Unmarshal(data, dst)
115 }
116
117 return nil
118 }
119
120 func (JSON) PreferredResultFormat() int16 {
121 return TextFormatCode
122 }
123
124 func (dst *JSON) DecodeText(ci *ConnInfo, src []byte) error {
125 if src == nil {
126 *dst = JSON{Status: Null}
127 return nil
128 }
129
130 *dst = JSON{Bytes: src, Status: Present}
131 return nil
132 }
133
134 func (dst *JSON) DecodeBinary(ci *ConnInfo, src []byte) error {
135 return dst.DecodeText(ci, src)
136 }
137
138 func (JSON) PreferredParamFormat() int16 {
139 return TextFormatCode
140 }
141
142 func (src JSON) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
143 switch src.Status {
144 case Null:
145 return nil, nil
146 case Undefined:
147 return nil, errUndefined
148 }
149
150 return append(buf, src.Bytes...), nil
151 }
152
153 func (src JSON) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
154 return src.EncodeText(ci, buf)
155 }
156
157
158 func (dst *JSON) Scan(src interface{}) error {
159 if src == nil {
160 *dst = JSON{Status: Null}
161 return nil
162 }
163
164 switch src := src.(type) {
165 case string:
166 return dst.DecodeText(nil, []byte(src))
167 case []byte:
168 srcCopy := make([]byte, len(src))
169 copy(srcCopy, src)
170 return dst.DecodeText(nil, srcCopy)
171 }
172
173 return fmt.Errorf("cannot scan %T", src)
174 }
175
176
177 func (src JSON) Value() (driver.Value, error) {
178 switch src.Status {
179 case Present:
180 return src.Bytes, nil
181 case Null:
182 return nil, nil
183 default:
184 return nil, errUndefined
185 }
186 }
187
188 func (src JSON) MarshalJSON() ([]byte, error) {
189 switch src.Status {
190 case Present:
191 return src.Bytes, nil
192 case Null:
193 return []byte("null"), nil
194 case Undefined:
195 return nil, errUndefined
196 }
197
198 return nil, errBadStatus
199 }
200
201 func (dst *JSON) UnmarshalJSON(b []byte) error {
202 if b == nil || string(b) == "null" {
203 *dst = JSON{Status: Null}
204 } else {
205 *dst = JSON{Bytes: b, Status: Present}
206 }
207 return nil
208
209 }
210
View as plain text