1
2
3
4
5
6
7 package json
8
9 import (
10 "cmp"
11 "errors"
12 "fmt"
13 "io"
14 "reflect"
15 "strconv"
16 "strings"
17 "sync"
18
19 "encoding/json/internal/jsonflags"
20 "encoding/json/internal/jsonopts"
21 "encoding/json/internal/jsonwire"
22 "encoding/json/jsontext"
23 )
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 var ErrUnknownName = errors.New("unknown object member name")
41
42
43
44 var errAmbiguousName = errors.New("ambiguous object member name")
45
46 const errorPrefix = "json: "
47
48 func isSemanticError(err error) bool {
49 _, ok := err.(*SemanticError)
50 return ok
51 }
52
53 func isSyntacticError(err error) bool {
54 _, ok := err.(*jsontext.SyntacticError)
55 return ok
56 }
57
58
59
60
61
62 func isFatalError(err error, flags jsonflags.Flags) bool {
63 return !flags.Get(jsonflags.ReportErrorsWithLegacySemantics) ||
64 isSyntacticError(err) || export.IsIOError(err)
65 }
66
67
68
69
70
71
72
73
74
75
76 type SemanticError struct {
77 requireKeyedLiterals
78 nonComparable
79
80 action string
81
82
83 ByteOffset int64
84
85
86 JSONPointer jsontext.Pointer
87
88
89 JSONKind jsontext.Kind
90
91
92 JSONValue jsontext.Value
93
94 GoType reflect.Type
95
96
97 Err error
98 }
99
100
101 type coder interface {
102 StackPointer() jsontext.Pointer
103 Options() Options
104 }
105
106
107
108
109
110
111
112
113 func newInvalidFormatError(c coder, t reflect.Type) error {
114 err := fmt.Errorf("invalid format flag %q", c.Options().(*jsonopts.Struct).Format)
115 switch c := c.(type) {
116 case *jsontext.Encoder:
117 err = newMarshalErrorBefore(c, t, err)
118 case *jsontext.Decoder:
119 err = newUnmarshalErrorBeforeWithSkipping(c, t, err)
120 }
121 return err
122 }
123
124
125
126 func newMarshalErrorBefore(e *jsontext.Encoder, t reflect.Type, err error) error {
127 return &SemanticError{action: "marshal", GoType: t, Err: toUnexpectedEOF(err),
128 ByteOffset: e.OutputOffset() + int64(export.Encoder(e).CountNextDelimWhitespace()),
129 JSONPointer: jsontext.Pointer(export.Encoder(e).AppendStackPointer(nil, +1))}
130 }
131
132
133
134
135
136
137
138 func newUnmarshalErrorBefore(d *jsontext.Decoder, t reflect.Type, err error) error {
139 var k jsontext.Kind
140 if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
141 k = d.PeekKind()
142 }
143 return &SemanticError{action: "unmarshal", GoType: t, Err: toUnexpectedEOF(err),
144 ByteOffset: d.InputOffset() + int64(export.Decoder(d).CountNextDelimWhitespace()),
145 JSONPointer: jsontext.Pointer(export.Decoder(d).AppendStackPointer(nil, +1)),
146 JSONKind: k}
147 }
148
149
150
151
152 func newUnmarshalErrorBeforeWithSkipping(d *jsontext.Decoder, t reflect.Type, err error) error {
153 err = newUnmarshalErrorBefore(d, t, err)
154 if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
155 if err2 := export.Decoder(d).SkipValue(); err2 != nil {
156 return err2
157 }
158 }
159 return err
160 }
161
162
163
164 func newUnmarshalErrorAfter(d *jsontext.Decoder, t reflect.Type, err error) error {
165 tokOrVal := export.Decoder(d).PreviousTokenOrValue()
166 byteOffset := d.InputOffset() - int64(len(tokOrVal))
167 if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
168
169 if k := jsontext.Value(tokOrVal).Kind(); k == '[' || k == '{' {
170 byteOffset++
171 } else {
172 byteOffset += int64(len(tokOrVal))
173 }
174 }
175 return &SemanticError{action: "unmarshal", GoType: t, Err: toUnexpectedEOF(err),
176 ByteOffset: byteOffset,
177 JSONPointer: jsontext.Pointer(export.Decoder(d).AppendStackPointer(nil, -1)),
178 JSONKind: jsontext.Value(tokOrVal).Kind()}
179 }
180
181
182
183
184 func newUnmarshalErrorAfterWithValue(d *jsontext.Decoder, t reflect.Type, err error) error {
185 serr := newUnmarshalErrorAfter(d, t, err).(*SemanticError)
186 if serr.JSONKind == '"' || serr.JSONKind == '0' {
187 serr.JSONValue = jsontext.Value(export.Decoder(d).PreviousTokenOrValue()).Clone()
188 }
189 return serr
190 }
191
192
193
194
195 func newUnmarshalErrorAfterWithSkipping(d *jsontext.Decoder, t reflect.Type, err error) error {
196 err = newUnmarshalErrorAfter(d, t, err)
197 if export.Decoder(d).Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
198 if err2 := export.Decoder(d).SkipValueRemainder(); err2 != nil {
199 return err2
200 }
201 }
202 return err
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 func newSemanticErrorWithPosition(c coder, t reflect.Type, prevDepth int, prevLength int64, err error) error {
220 serr, _ := err.(*SemanticError)
221 if serr == nil {
222 serr = &SemanticError{Err: err}
223 }
224 serr.Err = toUnexpectedEOF(serr.Err)
225 var currDepth int
226 var currLength int64
227 var coderState interface{ AppendStackPointer([]byte, int) []byte }
228 var offset int64
229 switch c := c.(type) {
230 case *jsontext.Encoder:
231 e := export.Encoder(c)
232 serr.action = cmp.Or(serr.action, "marshal")
233 currDepth, currLength = e.Tokens.DepthLength()
234 offset = c.OutputOffset() + int64(export.Encoder(c).CountNextDelimWhitespace())
235 coderState = e
236 case *jsontext.Decoder:
237 d := export.Decoder(c)
238 serr.action = cmp.Or(serr.action, "unmarshal")
239 currDepth, currLength = d.Tokens.DepthLength()
240 tokOrVal := d.PreviousTokenOrValue()
241 offset = c.InputOffset() - int64(len(tokOrVal))
242 if (prevDepth == currDepth && prevLength == currLength) || len(tokOrVal) == 0 {
243
244
245 offset = c.InputOffset() + int64(export.Decoder(c).CountNextDelimWhitespace())
246 }
247 coderState = d
248 }
249 serr.ByteOffset = cmp.Or(serr.ByteOffset, offset)
250 if serr.JSONPointer == "" {
251 where := 0
252 switch {
253 case prevDepth == currDepth && prevLength+0 == currLength:
254 where = +1
255 case prevDepth == currDepth && prevLength+1 == currLength:
256 where = -1
257 }
258 serr.JSONPointer = jsontext.Pointer(coderState.AppendStackPointer(nil, where))
259 }
260 serr.GoType = cmp.Or(serr.GoType, t)
261 return serr
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304 func collapseSemanticErrors(err error) error {
305 if serr1, ok := err.(*SemanticError); ok {
306 if serr2, ok := serr1.Err.(*SemanticError); ok {
307 serr2.ByteOffset = serr1.ByteOffset + serr2.ByteOffset
308 serr2.JSONPointer = serr1.JSONPointer + serr2.JSONPointer
309 *serr1 = *serr2
310 }
311 }
312 return err
313 }
314
315 func wrapErrUnsupported(err error, what string) error {
316 if errors.Is(err, errors.ErrUnsupported) {
317 return errors.New(what + " may not return errors.ErrUnsupported")
318 }
319 return err
320 }
321
322
323
324
325
326
327
328 var errorModalVerb = sync.OnceValue(func() string {
329 for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} {
330 return phrase
331 }
332 return ""
333 })
334
335 func (e *SemanticError) Error() string {
336 var sb strings.Builder
337 sb.WriteString(errorPrefix)
338 sb.WriteString(errorModalVerb())
339
340
341 var preposition string
342 switch e.action {
343 case "marshal":
344 sb.WriteString(" marshal")
345 preposition = " from"
346 case "unmarshal":
347 sb.WriteString(" unmarshal")
348 preposition = " into"
349 default:
350 sb.WriteString(" handle")
351 preposition = " with"
352 }
353
354
355 switch e.JSONKind {
356 case 'n':
357 sb.WriteString(" JSON null")
358 case 'f', 't':
359 sb.WriteString(" JSON boolean")
360 case '"':
361 sb.WriteString(" JSON string")
362 case '0':
363 sb.WriteString(" JSON number")
364 case '{', '}':
365 sb.WriteString(" JSON object")
366 case '[', ']':
367 sb.WriteString(" JSON array")
368 default:
369 if e.action == "" {
370 preposition = ""
371 }
372 }
373 if len(e.JSONValue) > 0 && len(e.JSONValue) < 100 {
374 sb.WriteByte(' ')
375 sb.Write(e.JSONValue)
376 }
377
378
379 if e.GoType != nil {
380 typeString := e.GoType.String()
381 if len(typeString) > 100 {
382
383
384
385
386
387 typeString = e.GoType.Kind().String()
388 if e.GoType.Kind() == reflect.Struct && e.GoType.Name() == "" {
389 for i := range e.GoType.NumField() {
390 if pkgPath := e.GoType.Field(i).PkgPath; pkgPath != "" {
391 typeString = pkgPath[strings.LastIndexByte(pkgPath, '/')+len("/"):] + ".struct"
392 break
393 }
394 }
395 }
396 }
397 sb.WriteString(preposition)
398 sb.WriteString(" Go ")
399 sb.WriteString(typeString)
400 }
401
402
403 if e.Err == ErrUnknownName || e.Err == errAmbiguousName {
404 sb.WriteString(": ")
405 sb.WriteString(e.Err.Error())
406 sb.WriteString(" ")
407 sb.WriteString(strconv.Quote(e.JSONPointer.LastToken()))
408 if parent := e.JSONPointer.Parent(); parent != "" {
409 sb.WriteString(" within ")
410 sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(parent), 100)))
411 }
412 return sb.String()
413 }
414
415
416
417 switch serr, _ := e.Err.(*jsontext.SyntacticError); {
418 case e.JSONPointer != "":
419 if serr == nil || !e.JSONPointer.Contains(serr.JSONPointer) {
420 sb.WriteString(" within ")
421 sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(e.JSONPointer), 100)))
422 }
423 case e.ByteOffset > 0:
424 if serr == nil || !(e.ByteOffset <= serr.ByteOffset) {
425 sb.WriteString(" after offset ")
426 sb.WriteString(strconv.FormatInt(e.ByteOffset, 10))
427 }
428 }
429
430
431 if e.Err != nil {
432 errString := e.Err.Error()
433 if isSyntacticError(e.Err) {
434 errString = strings.TrimPrefix(errString, "jsontext: ")
435 }
436 sb.WriteString(": ")
437 sb.WriteString(errString)
438 }
439
440 return sb.String()
441 }
442
443 func (e *SemanticError) Unwrap() error {
444 return e.Err
445 }
446
447 func newDuplicateNameError(ptr jsontext.Pointer, quotedName []byte, offset int64) error {
448 if quotedName != nil {
449 name, _ := jsonwire.AppendUnquote(nil, quotedName)
450 ptr = ptr.AppendToken(string(name))
451 }
452 return &jsontext.SyntacticError{
453 ByteOffset: offset,
454 JSONPointer: ptr,
455 Err: jsontext.ErrDuplicateName,
456 }
457 }
458
459
460 func toUnexpectedEOF(err error) error {
461 if err == io.EOF {
462 return io.ErrUnexpectedEOF
463 }
464 return err
465 }
466
View as plain text