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