1
2
3
4
5
6
7 package json
8
9 import (
10 "encoding"
11 "errors"
12 "io"
13 "reflect"
14
15 "encoding/json/internal"
16 "encoding/json/internal/jsonflags"
17 "encoding/json/internal/jsonopts"
18 "encoding/json/internal/jsonwire"
19 "encoding/json/jsontext"
20 )
21
22 var errNonStringValue = errors.New("JSON value must be string type")
23
24
25 var (
26 jsonMarshalerType = reflect.TypeFor[Marshaler]()
27 jsonMarshalerToType = reflect.TypeFor[MarshalerTo]()
28 jsonUnmarshalerType = reflect.TypeFor[Unmarshaler]()
29 jsonUnmarshalerFromType = reflect.TypeFor[UnmarshalerFrom]()
30 textAppenderType = reflect.TypeFor[encoding.TextAppender]()
31 textMarshalerType = reflect.TypeFor[encoding.TextMarshaler]()
32 textUnmarshalerType = reflect.TypeFor[encoding.TextUnmarshaler]()
33
34 allMarshalerTypes = []reflect.Type{jsonMarshalerToType, jsonMarshalerType, textAppenderType, textMarshalerType}
35 allUnmarshalerTypes = []reflect.Type{jsonUnmarshalerFromType, jsonUnmarshalerType, textUnmarshalerType}
36 allMethodTypes = append(allMarshalerTypes, allUnmarshalerTypes...)
37 )
38
39
40
41
42
43
44
45
46
47
48
49 type Marshaler interface {
50 MarshalJSON() ([]byte, error)
51 }
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 type MarshalerTo interface {
68 MarshalJSONTo(*jsontext.Encoder) error
69
70
71
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 type Unmarshaler interface {
90 UnmarshalJSON([]byte) error
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 type UnmarshalerFrom interface {
111 UnmarshalJSONFrom(*jsontext.Decoder) error
112
113
114
115 }
116
117 func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
118
119
120
121 if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
122 return fncs
123 }
124
125 if needAddr, ok := implements(t, textMarshalerType); ok {
126 fncs.nonDefault = true
127 prevMarshal := fncs.marshal
128 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
129 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
130 (needAddr && va.forcedAddr) {
131 return prevMarshal(enc, va, mo)
132 }
133 marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
134 if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
135 b2, err := marshaler.MarshalText()
136 return append(b, b2...), err
137 }); err != nil {
138 err = wrapSkipFunc(err, "marshal method")
139 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
140 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText")
141 }
142 if !isSemanticError(err) && !export.IsIOError(err) {
143 err = newMarshalErrorBefore(enc, t, err)
144 }
145 return err
146 }
147 return nil
148 }
149 }
150
151 if needAddr, ok := implements(t, textAppenderType); ok {
152 fncs.nonDefault = true
153 prevMarshal := fncs.marshal
154 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
155 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
156 (needAddr && va.forcedAddr) {
157 return prevMarshal(enc, va, mo)
158 }
159 appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
160 if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
161 err = wrapSkipFunc(err, "append method")
162 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
163 return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText")
164 }
165 if !isSemanticError(err) && !export.IsIOError(err) {
166 err = newMarshalErrorBefore(enc, t, err)
167 }
168 return err
169 }
170 return nil
171 }
172 }
173
174 if needAddr, ok := implements(t, jsonMarshalerType); ok {
175 fncs.nonDefault = true
176 prevMarshal := fncs.marshal
177 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
178 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
179 ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
180 return prevMarshal(enc, va, mo)
181 }
182 marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
183 val, err := marshaler.MarshalJSON()
184 if err != nil {
185 err = wrapSkipFunc(err, "marshal method")
186 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
187 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON")
188 }
189 err = newMarshalErrorBefore(enc, t, err)
190 return collapseSemanticErrors(err)
191 }
192 if err := enc.WriteValue(val); err != nil {
193 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
194 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON")
195 }
196 if isSyntacticError(err) {
197 err = newMarshalErrorBefore(enc, t, err)
198 }
199 return err
200 }
201 return nil
202 }
203 }
204
205 if needAddr, ok := implements(t, jsonMarshalerToType); ok {
206 fncs.nonDefault = true
207 prevMarshal := fncs.marshal
208 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
209 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
210 ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
211 return prevMarshal(enc, va, mo)
212 }
213 xe := export.Encoder(enc)
214 prevDepth, prevLength := xe.Tokens.DepthLength()
215 xe.Flags.Set(jsonflags.WithinArshalCall | 1)
216 marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
217 err := marshaler.MarshalJSONTo(enc)
218 xe.Flags.Set(jsonflags.WithinArshalCall | 0)
219 currDepth, currLength := xe.Tokens.DepthLength()
220 if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
221 err = errNonSingularValue
222 }
223 if err != nil {
224 err = wrapSkipFunc(err, "marshal method")
225 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
226 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo")
227 }
228 if !export.IsIOError(err) {
229 err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
230 }
231 return err
232 }
233 return nil
234 }
235 }
236
237 if _, ok := implements(t, textUnmarshalerType); ok {
238 fncs.nonDefault = true
239 fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
240 xd := export.Decoder(dec)
241 var flags jsonwire.ValueFlags
242 val, err := xd.ReadValue(&flags)
243 if err != nil {
244 return err
245 }
246 if val.Kind() == 'n' {
247 if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
248 va.SetZero()
249 }
250 return nil
251 }
252 if val.Kind() != '"' {
253 return newUnmarshalErrorAfter(dec, t, errNonStringValue)
254 }
255 s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
256 unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
257 if err := unmarshaler.UnmarshalText(s); err != nil {
258 err = wrapSkipFunc(err, "unmarshal method")
259 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
260 return err
261 }
262 if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) {
263 err = newUnmarshalErrorAfter(dec, t, err)
264 }
265 return err
266 }
267 return nil
268 }
269 }
270
271 if _, ok := implements(t, jsonUnmarshalerType); ok {
272 fncs.nonDefault = true
273 prevUnmarshal := fncs.unmarshal
274 fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
275 if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
276 export.Decoder(dec).Tokens.Last.NeedObjectName() {
277 return prevUnmarshal(dec, va, uo)
278 }
279 val, err := dec.ReadValue()
280 if err != nil {
281 return err
282 }
283 unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
284 if err := unmarshaler.UnmarshalJSON(val); err != nil {
285 err = wrapSkipFunc(err, "unmarshal method")
286 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
287 return err
288 }
289 err = newUnmarshalErrorAfter(dec, t, err)
290 return collapseSemanticErrors(err)
291 }
292 return nil
293 }
294 }
295
296 if _, ok := implements(t, jsonUnmarshalerFromType); ok {
297 fncs.nonDefault = true
298 prevUnmarshal := fncs.unmarshal
299 fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
300 if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
301 export.Decoder(dec).Tokens.Last.NeedObjectName() {
302 return prevUnmarshal(dec, va, uo)
303 }
304 xd := export.Decoder(dec)
305 prevDepth, prevLength := xd.Tokens.DepthLength()
306 if prevDepth == 1 && xd.AtEOF() {
307 return io.EOF
308 }
309 xd.Flags.Set(jsonflags.WithinArshalCall | 1)
310 unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
311 err := unmarshaler.UnmarshalJSONFrom(dec)
312 xd.Flags.Set(jsonflags.WithinArshalCall | 0)
313 currDepth, currLength := xd.Tokens.DepthLength()
314 if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
315 err = errNonSingularValue
316 }
317 if err != nil {
318 err = wrapSkipFunc(err, "unmarshal method")
319 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
320 if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
321 return err2
322 }
323 return err
324 }
325 if !isSyntacticError(err) && !export.IsIOError(err) {
326 err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
327 }
328 return err
329 }
330 return nil
331 }
332 }
333
334 return fncs
335 }
336
337
338
339 func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool {
340 for _, ifaceType := range ifaceTypes {
341 if _, ok := implements(t, ifaceType); ok {
342 return true
343 }
344 }
345 return false
346 }
347
348
349
350
351
352 func implements(t, ifaceType reflect.Type) (needAddr, ok bool) {
353 switch {
354 case t.Implements(ifaceType):
355 return false, true
356 case reflect.PointerTo(t).Implements(ifaceType):
357 return true, true
358 default:
359 return false, false
360 }
361 }
362
View as plain text