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