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