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