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
50
51
52
53
54 type Marshaler interface {
55 MarshalJSON() ([]byte, error)
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 type MarshalerTo interface {
100 MarshalJSONTo(*jsontext.Encoder) error
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 type Unmarshaler interface {
120 UnmarshalJSON([]byte) error
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 type UnmarshalerFrom interface {
165 UnmarshalJSONFrom(*jsontext.Decoder) error
166 }
167
168 func makeMethodMarshaler(fncs *marshaler, t reflect.Type) *marshaler {
169
170
171
172 if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
173 return fncs
174 }
175
176 if needAddr, ok := implements(t, textMarshalerType); ok {
177 fncs.nonDefault = true
178 prevMarshal := fncs.fnc
179 fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
180 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
181 ((needAddr && va.forcedAddr) ||
182 (va.forcedAddr && export.Encoder(enc).Tokens.Last.NeedObjectName() && t.Kind() == reflect.String)) {
183
184
185
186 return prevMarshal(enc, va, mo)
187 }
188 marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
189 if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
190 b2, err := marshaler.MarshalText()
191 return append(b, b2...), err
192 }); err != nil {
193 err = wrapErrUnsupported(err, "MarshalText method")
194 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
195 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText")
196 }
197 if !isSemanticError(err) && !export.IsIOError(err) {
198 err = newMarshalErrorBefore(enc, t, err)
199 }
200 return err
201 }
202 return nil
203 }
204 }
205
206 if needAddr, ok := implements(t, textAppenderType); ok {
207 fncs.nonDefault = true
208 prevMarshal := fncs.fnc
209 fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
210 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
211 ((needAddr && va.forcedAddr) ||
212 (va.forcedAddr && export.Encoder(enc).Tokens.Last.NeedObjectName() && t.Kind() == reflect.String)) {
213
214
215
216 return prevMarshal(enc, va, mo)
217 }
218 appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
219 if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
220 err = wrapErrUnsupported(err, "AppendText method")
221 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
222 return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText")
223 }
224 if !isSemanticError(err) && !export.IsIOError(err) {
225 err = newMarshalErrorBefore(enc, t, err)
226 }
227 return err
228 }
229 return nil
230 }
231 }
232
233 if needAddr, ok := implements(t, jsonMarshalerType); ok {
234 fncs.nonDefault = true
235 prevMarshal := fncs.fnc
236 fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
237 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
238 ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
239
240 return prevMarshal(enc, va, mo)
241 }
242 marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
243 val, err := marshaler.MarshalJSON()
244 if err != nil {
245 err = wrapErrUnsupported(err, "MarshalJSON method")
246 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
247 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON")
248 }
249 err = newMarshalErrorBefore(enc, t, err)
250 return collapseSemanticErrors(err)
251 }
252 if err := enc.WriteValue(val); err != nil {
253 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
254 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON")
255 }
256 if isSyntacticError(err) {
257 err = newMarshalErrorBefore(enc, t, err)
258 }
259 return err
260 }
261 return nil
262 }
263 }
264
265 if needAddr, ok := implements(t, jsonMarshalerToType); ok {
266 fncs.nonDefault = true
267 prevMarshal := fncs.fnc
268 fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
269 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
270 ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
271
272 return prevMarshal(enc, va, mo)
273 }
274 xe := export.Encoder(enc)
275 prevDepth, prevLength := xe.Tokens.DepthLength()
276 xe.Flags.Set(jsonflags.WithinArshalCall | 1)
277 marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
278 err := marshaler.MarshalJSONTo(enc)
279 xe.Flags.Set(jsonflags.WithinArshalCall | 0)
280 currDepth, currLength := xe.Tokens.DepthLength()
281 if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
282 err = errNonSingularValue
283 }
284 if err != nil {
285 if errors.Is(err, errors.ErrUnsupported) {
286 if prevDepth == currDepth && prevLength == currLength {
287 return prevMarshal(enc, va, mo)
288 }
289 err = errUnsupportedMutation
290 }
291 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
292 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo")
293 }
294 if !export.IsIOError(err) {
295 err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
296 }
297 return err
298 }
299 return nil
300 }
301 }
302
303 return fncs
304 }
305
306 func makeMethodUnmarshaler(fncs *unmarshaler, t reflect.Type) *unmarshaler {
307
308
309
310 if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
311 return fncs
312 }
313
314 if _, ok := implements(t, textUnmarshalerType); ok {
315 fncs.nonDefault = true
316 fncs.fnc = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
317 xd := export.Decoder(dec)
318 var flags jsonwire.ValueFlags
319 val, err := xd.ReadValue(&flags)
320 if err != nil {
321 return err
322 }
323 if val.Kind() == 'n' {
324 if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
325 va.SetZero()
326 }
327 return nil
328 }
329 if val.Kind() != '"' {
330 return newUnmarshalErrorAfter(dec, t, errNonStringValue)
331 }
332 s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
333 unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
334 if err := unmarshaler.UnmarshalText(s); err != nil {
335 err = wrapErrUnsupported(err, "UnmarshalText method")
336 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
337 return err
338 }
339 if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) {
340 err = newUnmarshalErrorAfter(dec, t, err)
341 }
342 return err
343 }
344 return nil
345 }
346 }
347
348 if _, ok := implements(t, jsonUnmarshalerType); ok {
349 fncs.nonDefault = true
350 prevUnmarshal := fncs.fnc
351 fncs.fnc = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
352 if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
353 export.Decoder(dec).Tokens.Last.NeedObjectName() {
354
355 return prevUnmarshal(dec, va, uo)
356 }
357 val, err := dec.ReadValue()
358 if err != nil {
359 return err
360 }
361 unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
362 if err := unmarshaler.UnmarshalJSON(val); err != nil {
363 err = wrapErrUnsupported(err, "UnmarshalJSON method")
364 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
365 return err
366 }
367 err = newUnmarshalErrorAfter(dec, t, err)
368 return collapseSemanticErrors(err)
369 }
370 return nil
371 }
372 }
373
374 if _, ok := implements(t, jsonUnmarshalerFromType); ok {
375 fncs.nonDefault = true
376 prevUnmarshal := fncs.fnc
377 fncs.fnc = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
378 if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
379 export.Decoder(dec).Tokens.Last.NeedObjectName() {
380
381 return prevUnmarshal(dec, va, uo)
382 }
383 xd := export.Decoder(dec)
384 prevDepth, prevLength := xd.Tokens.DepthLength()
385 if prevDepth == 1 && xd.AtEOF() {
386 return io.EOF
387 }
388 xd.Flags.Set(jsonflags.WithinArshalCall | 1)
389 unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
390 err := unmarshaler.UnmarshalJSONFrom(dec)
391 xd.Flags.Set(jsonflags.WithinArshalCall | 0)
392 currDepth, currLength := xd.Tokens.DepthLength()
393 if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
394 err = errNonSingularValue
395 }
396 if err != nil {
397 if errors.Is(err, errors.ErrUnsupported) {
398 if prevDepth == currDepth && prevLength == currLength {
399 return prevUnmarshal(dec, va, uo)
400 }
401 err = errUnsupportedMutation
402 }
403 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
404 if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
405 return err2
406 }
407 return err
408 }
409 if !isSyntacticError(err) && !export.IsIOError(err) {
410 err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
411 }
412 return err
413 }
414 return nil
415 }
416 }
417
418 return fncs
419 }
420
421
422
423 func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool {
424 for _, ifaceType := range ifaceTypes {
425 if _, ok := implements(t, ifaceType); ok {
426 return true
427 }
428 }
429 return false
430 }
431
432
433
434
435
436 func implements(t, ifaceType reflect.Type) (needAddr, ok bool) {
437 switch {
438 case t.Implements(ifaceType):
439 return false, true
440 case reflect.PointerTo(t).Implements(ifaceType):
441 return true, true
442 default:
443 return false, false
444 }
445 }
446
View as plain text