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