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