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
303
304
305
306
307
308 var errorModalVerb = sync.OnceValue(func() string {
309 for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} {
310 return phrase
311 }
312 return ""
313 })
314
315 func (e *SemanticError) Error() string {
316 var sb strings.Builder
317 sb.WriteString(errorPrefix)
318 sb.WriteString(errorModalVerb())
319
320
321 var preposition string
322 switch e.action {
323 case "marshal":
324 sb.WriteString(" marshal")
325 preposition = " from"
326 case "unmarshal":
327 sb.WriteString(" unmarshal")
328 preposition = " into"
329 default:
330 sb.WriteString(" handle")
331 preposition = " with"
332 }
333
334
335 switch e.JSONKind {
336 case 'n':
337 sb.WriteString(" JSON null")
338 case 'f', 't':
339 sb.WriteString(" JSON boolean")
340 case '"':
341 sb.WriteString(" JSON string")
342 case '0':
343 sb.WriteString(" JSON number")
344 case '{', '}':
345 sb.WriteString(" JSON object")
346 case '[', ']':
347 sb.WriteString(" JSON array")
348 default:
349 if e.action == "" {
350 preposition = ""
351 }
352 }
353 if len(e.JSONValue) > 0 && len(e.JSONValue) < 100 {
354 sb.WriteByte(' ')
355 sb.Write(e.JSONValue)
356 }
357
358
359 if e.GoType != nil {
360 typeString := e.GoType.String()
361 if len(typeString) > 100 {
362
363
364
365
366
367 typeString = e.GoType.Kind().String()
368 if e.GoType.Kind() == reflect.Struct && e.GoType.Name() == "" {
369 for i := range e.GoType.NumField() {
370 if pkgPath := e.GoType.Field(i).PkgPath; pkgPath != "" {
371 typeString = pkgPath[strings.LastIndexByte(pkgPath, '/')+len("/"):] + ".struct"
372 break
373 }
374 }
375 }
376 }
377 sb.WriteString(preposition)
378 sb.WriteString(" Go ")
379 sb.WriteString(typeString)
380 }
381
382
383 if e.Err == ErrUnknownName {
384 sb.WriteString(": ")
385 sb.WriteString(ErrUnknownName.Error())
386 sb.WriteString(" ")
387 sb.WriteString(strconv.Quote(e.JSONPointer.LastToken()))
388 if parent := e.JSONPointer.Parent(); parent != "" {
389 sb.WriteString(" within ")
390 sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(parent), 100)))
391 }
392 return sb.String()
393 }
394
395
396
397 switch serr, _ := e.Err.(*jsontext.SyntacticError); {
398 case e.JSONPointer != "":
399 if serr == nil || !e.JSONPointer.Contains(serr.JSONPointer) {
400 sb.WriteString(" within ")
401 sb.WriteString(strconv.Quote(jsonwire.TruncatePointer(string(e.JSONPointer), 100)))
402 }
403 case e.ByteOffset > 0:
404 if serr == nil || !(e.ByteOffset <= serr.ByteOffset) {
405 sb.WriteString(" after offset ")
406 sb.WriteString(strconv.FormatInt(e.ByteOffset, 10))
407 }
408 }
409
410
411 if e.Err != nil {
412 errString := e.Err.Error()
413 if isSyntacticError(e.Err) {
414 errString = strings.TrimPrefix(errString, "jsontext: ")
415 }
416 sb.WriteString(": ")
417 sb.WriteString(errString)
418 }
419
420 return sb.String()
421 }
422
423 func (e *SemanticError) Unwrap() error {
424 return e.Err
425 }
426
427 func newDuplicateNameError(ptr jsontext.Pointer, quotedName []byte, offset int64) error {
428 if quotedName != nil {
429 name, _ := jsonwire.AppendUnquote(nil, quotedName)
430 ptr = ptr.AppendToken(string(name))
431 }
432 return &jsontext.SyntacticError{
433 ByteOffset: offset,
434 JSONPointer: ptr,
435 Err: jsontext.ErrDuplicateName,
436 }
437 }
438
439
440 func toUnexpectedEOF(err error) error {
441 if err == io.EOF {
442 return io.ErrUnexpectedEOF
443 }
444 return err
445 }
446
View as plain text