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
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: 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: 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: 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 var currDepth int
211 var currLength int64
212 var coderState interface{ AppendStackPointer([]byte, int) []byte }
213 var offset int64
214 switch c := c.(type) {
215 case *jsontext.Encoder:
216 e := export.Encoder(c)
217 serr.action = cmp.Or(serr.action, "marshal")
218 currDepth, currLength = e.Tokens.DepthLength()
219 offset = c.OutputOffset() + int64(export.Encoder(c).CountNextDelimWhitespace())
220 coderState = e
221 case *jsontext.Decoder:
222 d := export.Decoder(c)
223 serr.action = cmp.Or(serr.action, "unmarshal")
224 currDepth, currLength = d.Tokens.DepthLength()
225 tokOrVal := d.PreviousTokenOrValue()
226 offset = c.InputOffset() - int64(len(tokOrVal))
227 if (prevDepth == currDepth && prevLength == currLength) || len(tokOrVal) == 0 {
228
229
230 offset = c.InputOffset() + int64(export.Decoder(c).CountNextDelimWhitespace())
231 }
232 coderState = d
233 }
234 serr.ByteOffset = cmp.Or(serr.ByteOffset, offset)
235 if serr.JSONPointer == "" {
236 where := 0
237 switch {
238 case prevDepth == currDepth && prevLength+0 == currLength:
239 where = +1
240 case prevDepth == currDepth && prevLength+1 == currLength:
241 where = -1
242 }
243 serr.JSONPointer = jsontext.Pointer(coderState.AppendStackPointer(nil, where))
244 }
245 serr.GoType = cmp.Or(serr.GoType, t)
246 return serr
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
285
286
287
288
289 func collapseSemanticErrors(err error) error {
290 if serr1, ok := err.(*SemanticError); ok {
291 if serr2, ok := serr1.Err.(*SemanticError); ok {
292 serr2.ByteOffset = serr1.ByteOffset + serr2.ByteOffset
293 serr2.JSONPointer = serr1.JSONPointer + serr2.JSONPointer
294 *serr1 = *serr2
295 }
296 }
297 return err
298 }
299
300
301
302
303
304
305
306 var errorModalVerb = sync.OnceValue(func() string {
307 for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} {
308 return phrase
309 }
310 return ""
311 })
312
313 func (e *SemanticError) Error() string {
314 var sb strings.Builder
315 sb.WriteString(errorPrefix)
316 sb.WriteString(errorModalVerb())
317
318
319 var preposition string
320 switch e.action {
321 case "marshal":
322 sb.WriteString(" marshal")
323 preposition = " from"
324 case "unmarshal":
325 sb.WriteString(" unmarshal")
326 preposition = " into"
327 default:
328 sb.WriteString(" handle")
329 preposition = " with"
330 }
331
332
333 switch e.JSONKind {
334 case 'n':
335 sb.WriteString(" JSON null")
336 case 'f', 't':
337 sb.WriteString(" JSON boolean")
338 case '"':
339 sb.WriteString(" JSON string")
340 case '0':
341 sb.WriteString(" JSON number")
342 case '{', '}':
343 sb.WriteString(" JSON object")
344 case '[', ']':
345 sb.WriteString(" JSON array")
346 default:
347 if e.action == "" {
348 preposition = ""
349 }
350 }
351 if len(e.JSONValue) > 0 && len(e.JSONValue) < 100 {
352 sb.WriteByte(' ')
353 sb.Write(e.JSONValue)
354 }
355
356
357 if e.GoType != nil {
358 typeString := e.GoType.String()
359 if len(typeString) > 100 {
360
361
362
363
364
365 typeString = e.GoType.Kind().String()
366 if e.GoType.Kind() == reflect.Struct && e.GoType.Name() == "" {
367 for i := range e.GoType.NumField() {
368 if pkgPath := e.GoType.Field(i).PkgPath; pkgPath != "" {
369 typeString = pkgPath[strings.LastIndexByte(pkgPath, '/')+len("/"):] + ".struct"
370 break
371 }
372 }
373 }
374 }
375 sb.WriteString(preposition)
376 sb.WriteString(" Go ")
377 sb.WriteString(typeString)
378 }
379
380
381 if e.Err == ErrUnknownName {
382 sb.WriteString(": ")
383 sb.WriteString(ErrUnknownName.Error())
384 sb.WriteString(" ")
385 sb.WriteString(strconv.Quote(e.JSONPointer.LastToken()))
386 if parent := e.JSONPointer.Parent(); parent != "" {
387 sb.WriteString(" within ")
388 sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(parent), 100)))
389 }
390 return sb.String()
391 }
392
393
394
395 switch serr, _ := e.Err.(*jsontext.SyntacticError); {
396 case e.JSONPointer != "":
397 if serr == nil || !e.JSONPointer.Contains(serr.JSONPointer) {
398 sb.WriteString(" within ")
399 sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(e.JSONPointer), 100)))
400 }
401 case e.ByteOffset > 0:
402 if serr == nil || !(e.ByteOffset <= serr.ByteOffset) {
403 sb.WriteString(" after offset ")
404 sb.WriteString(strconv.FormatInt(e.ByteOffset, 10))
405 }
406 }
407
408
409 if e.Err != nil {
410 errString := e.Err.Error()
411 if isSyntacticError(e.Err) {
412 errString = strings.TrimPrefix(errString, "jsontext: ")
413 }
414 sb.WriteString(": ")
415 sb.WriteString(errString)
416 }
417
418 return sb.String()
419 }
420
421 func (e *SemanticError) Unwrap() error {
422 return e.Err
423 }
424
425 func newDuplicateNameError(ptr jsontext.Pointer, quotedName []byte, offset int64) error {
426 if quotedName != nil {
427 name, _ := jsonwire.AppendUnquote(nil, quotedName)
428 ptr = ptr.AppendToken(string(name))
429 }
430 return &jsontext.SyntacticError{
431 ByteOffset: offset,
432 JSONPointer: ptr,
433 Err: jsontext.ErrDuplicateName,
434 }
435 }
436
View as plain text