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