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 makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
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.marshal
179 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
180 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
181 ((needAddr && va.forcedAddr) ||
182 (export.Encoder(enc).Tokens.Last.NeedObjectName()) && t.Kind() == reflect.String) {
183
184 return prevMarshal(enc, va, mo)
185 }
186 marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
187 if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
188 b2, err := marshaler.MarshalText()
189 return append(b, b2...), err
190 }); err != nil {
191 err = wrapErrUnsupported(err, "MarshalText method")
192 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
193 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText")
194 }
195 if !isSemanticError(err) && !export.IsIOError(err) {
196 err = newMarshalErrorBefore(enc, t, err)
197 }
198 return err
199 }
200 return nil
201 }
202 }
203
204 if needAddr, ok := implements(t, textAppenderType); ok {
205 fncs.nonDefault = true
206 prevMarshal := fncs.marshal
207 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
208 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
209 ((needAddr && va.forcedAddr) ||
210 (export.Encoder(enc).Tokens.Last.NeedObjectName()) && t.Kind() == reflect.String) {
211
212 return prevMarshal(enc, va, mo)
213 }
214 appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
215 if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
216 err = wrapErrUnsupported(err, "AppendText method")
217 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
218 return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText")
219 }
220 if !isSemanticError(err) && !export.IsIOError(err) {
221 err = newMarshalErrorBefore(enc, t, err)
222 }
223 return err
224 }
225 return nil
226 }
227 }
228
229 if needAddr, ok := implements(t, jsonMarshalerType); ok {
230 fncs.nonDefault = true
231 prevMarshal := fncs.marshal
232 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
233 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
234 ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
235
236 return prevMarshal(enc, va, mo)
237 }
238 marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
239 val, err := marshaler.MarshalJSON()
240 if err != nil {
241 err = wrapErrUnsupported(err, "MarshalJSON method")
242 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
243 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON")
244 }
245 err = newMarshalErrorBefore(enc, t, err)
246 return collapseSemanticErrors(err)
247 }
248 if err := enc.WriteValue(val); err != nil {
249 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
250 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON")
251 }
252 if isSyntacticError(err) {
253 err = newMarshalErrorBefore(enc, t, err)
254 }
255 return err
256 }
257 return nil
258 }
259 }
260
261 if needAddr, ok := implements(t, jsonMarshalerToType); ok {
262 fncs.nonDefault = true
263 prevMarshal := fncs.marshal
264 fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
265 if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
266 ((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
267
268 return prevMarshal(enc, va, mo)
269 }
270 xe := export.Encoder(enc)
271 prevDepth, prevLength := xe.Tokens.DepthLength()
272 xe.Flags.Set(jsonflags.WithinArshalCall | 1)
273 marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
274 err := marshaler.MarshalJSONTo(enc)
275 xe.Flags.Set(jsonflags.WithinArshalCall | 0)
276 currDepth, currLength := xe.Tokens.DepthLength()
277 if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
278 err = errNonSingularValue
279 }
280 if err != nil {
281 if errors.Is(err, errors.ErrUnsupported) {
282 if prevDepth == currDepth && prevLength == currLength {
283 return prevMarshal(enc, va, mo)
284 }
285 err = errUnsupportedMutation
286 }
287 if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
288 return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo")
289 }
290 if !export.IsIOError(err) {
291 err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
292 }
293 return err
294 }
295 return nil
296 }
297 }
298
299 if _, ok := implements(t, textUnmarshalerType); ok {
300 fncs.nonDefault = true
301 fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
302 xd := export.Decoder(dec)
303 var flags jsonwire.ValueFlags
304 val, err := xd.ReadValue(&flags)
305 if err != nil {
306 return err
307 }
308 if val.Kind() == 'n' {
309 if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
310 va.SetZero()
311 }
312 return nil
313 }
314 if val.Kind() != '"' {
315 return newUnmarshalErrorAfter(dec, t, errNonStringValue)
316 }
317 s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
318 unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
319 if err := unmarshaler.UnmarshalText(s); err != nil {
320 err = wrapErrUnsupported(err, "UnmarshalText method")
321 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
322 return err
323 }
324 if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) {
325 err = newUnmarshalErrorAfter(dec, t, err)
326 }
327 return err
328 }
329 return nil
330 }
331 }
332
333 if _, ok := implements(t, jsonUnmarshalerType); ok {
334 fncs.nonDefault = true
335 prevUnmarshal := fncs.unmarshal
336 fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
337 if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
338 export.Decoder(dec).Tokens.Last.NeedObjectName() {
339
340 return prevUnmarshal(dec, va, uo)
341 }
342 val, err := dec.ReadValue()
343 if err != nil {
344 return err
345 }
346 unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
347 if err := unmarshaler.UnmarshalJSON(val); err != nil {
348 err = wrapErrUnsupported(err, "UnmarshalJSON method")
349 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
350 return err
351 }
352 err = newUnmarshalErrorAfter(dec, t, err)
353 return collapseSemanticErrors(err)
354 }
355 return nil
356 }
357 }
358
359 if _, ok := implements(t, jsonUnmarshalerFromType); ok {
360 fncs.nonDefault = true
361 prevUnmarshal := fncs.unmarshal
362 fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
363 if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
364 export.Decoder(dec).Tokens.Last.NeedObjectName() {
365
366 return prevUnmarshal(dec, va, uo)
367 }
368 xd := export.Decoder(dec)
369 prevDepth, prevLength := xd.Tokens.DepthLength()
370 if prevDepth == 1 && xd.AtEOF() {
371 return io.EOF
372 }
373 xd.Flags.Set(jsonflags.WithinArshalCall | 1)
374 unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
375 err := unmarshaler.UnmarshalJSONFrom(dec)
376 xd.Flags.Set(jsonflags.WithinArshalCall | 0)
377 currDepth, currLength := xd.Tokens.DepthLength()
378 if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
379 err = errNonSingularValue
380 }
381 if err != nil {
382 if errors.Is(err, errors.ErrUnsupported) {
383 if prevDepth == currDepth && prevLength == currLength {
384 return prevUnmarshal(dec, va, uo)
385 }
386 err = errUnsupportedMutation
387 }
388 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
389 if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
390 return err2
391 }
392 return err
393 }
394 if !isSyntacticError(err) && !export.IsIOError(err) {
395 err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
396 }
397 return err
398 }
399 return nil
400 }
401 }
402
403 return fncs
404 }
405
406
407
408 func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool {
409 for _, ifaceType := range ifaceTypes {
410 if _, ok := implements(t, ifaceType); ok {
411 return true
412 }
413 }
414 return false
415 }
416
417
418
419
420
421 func implements(t, ifaceType reflect.Type) (needAddr, ok bool) {
422 switch {
423 case t.Implements(ifaceType):
424 return false, true
425 case reflect.PointerTo(t).Implements(ifaceType):
426 return true, true
427 default:
428 return false, false
429 }
430 }
431
View as plain text