...
1
2
3
4
5 package json
6
7 import (
8 "errors"
9 "reflect"
10 "strconv"
11 "strings"
12 "unicode/utf8"
13 )
14
15 const errorPrefix = "json: "
16
17
18 const Error = jsonError("json error")
19
20 type jsonError string
21
22 func (e jsonError) Error() string {
23 return string(e)
24 }
25 func (e jsonError) Is(target error) bool {
26 return e == target || target == Error
27 }
28
29 type ioError struct {
30 action string
31 err error
32 }
33
34 func (e *ioError) Error() string {
35 return errorPrefix + e.action + " error: " + e.err.Error()
36 }
37 func (e *ioError) Unwrap() error {
38 return e.err
39 }
40 func (e *ioError) Is(target error) bool {
41 return e == target || target == Error || errors.Is(e.err, target)
42 }
43
44
45
46
47
48 type SemanticError struct {
49 requireKeyedLiterals
50 nonComparable
51
52 action string
53
54
55 ByteOffset int64
56
57
58 JSONPointer string
59
60
61 JSONKind Kind
62
63 GoType reflect.Type
64
65
66 Err error
67 }
68
69 func (e *SemanticError) Error() string {
70 var sb strings.Builder
71 sb.WriteString(errorPrefix)
72
73
74
75
76
77 for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} {
78 sb.WriteString(phrase)
79 break
80 }
81
82
83 var preposition string
84 switch e.action {
85 case "marshal":
86 sb.WriteString(" marshal")
87 preposition = " from"
88 case "unmarshal":
89 sb.WriteString(" unmarshal")
90 preposition = " into"
91 default:
92 sb.WriteString(" handle")
93 preposition = " with"
94 }
95
96
97 var omitPreposition bool
98 switch e.JSONKind {
99 case 'n':
100 sb.WriteString(" JSON null")
101 case 'f', 't':
102 sb.WriteString(" JSON boolean")
103 case '"':
104 sb.WriteString(" JSON string")
105 case '0':
106 sb.WriteString(" JSON number")
107 case '{', '}':
108 sb.WriteString(" JSON object")
109 case '[', ']':
110 sb.WriteString(" JSON array")
111 default:
112 omitPreposition = true
113 }
114
115
116 if e.GoType != nil {
117 if !omitPreposition {
118 sb.WriteString(preposition)
119 }
120 sb.WriteString(" Go value of type ")
121 sb.WriteString(e.GoType.String())
122 }
123
124
125 switch {
126 case e.JSONPointer != "":
127 sb.WriteString(" within JSON value at ")
128 sb.WriteString(strconv.Quote(e.JSONPointer))
129 case e.ByteOffset > 0:
130 sb.WriteString(" after byte offset ")
131 sb.WriteString(strconv.FormatInt(e.ByteOffset, 10))
132 }
133
134
135 if e.Err != nil {
136 sb.WriteString(": ")
137 sb.WriteString(e.Err.Error())
138 }
139
140 return sb.String()
141 }
142 func (e *SemanticError) Is(target error) bool {
143 return e == target || target == Error || errors.Is(e.Err, target)
144 }
145 func (e *SemanticError) Unwrap() error {
146 return e.Err
147 }
148
149
150
151
152
153 type SyntacticError struct {
154 requireKeyedLiterals
155 nonComparable
156
157
158 ByteOffset int64
159 str string
160 }
161
162 func (e *SyntacticError) Error() string {
163 return errorPrefix + e.str
164 }
165 func (e *SyntacticError) Is(target error) bool {
166 return e == target || target == Error
167 }
168 func (e *SyntacticError) withOffset(pos int64) error {
169 return &SyntacticError{ByteOffset: pos, str: e.str}
170 }
171
172 func newInvalidCharacterError(prefix []byte, where string) *SyntacticError {
173 what := quoteRune(prefix)
174 return &SyntacticError{str: "invalid character " + what + " " + where}
175 }
176
177 func quoteRune(b []byte) string {
178 r, n := utf8.DecodeRune(b)
179 if r == utf8.RuneError && n == 1 {
180 return `'\x` + strconv.FormatUint(uint64(b[0]), 16) + `'`
181 }
182 return strconv.QuoteRune(r)
183 }
184
View as plain text