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