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