1 // Copyright 2017 Serde Developers
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
9 //! When serializing or deserializing JSON goes wrong.
12 use std
::fmt
::{self, Debug, Display}
;
19 /// This type represents all possible errors that can occur when serializing or
20 /// deserializing JSON data.
22 /// This `Box` allows us to keep the size of `Error` as small as possible. A
23 /// larger `Error` type was substantially slower due to all the functions
24 /// that pass around `Result<T, Error>`.
28 /// Alias for a `Result` with the error type `serde_json::Error`.
29 pub type Result
<T
> = result
::Result
<T
, Error
>;
32 /// One-based line number at which the error was detected.
34 /// Characters in the first line of the input (before the first newline
35 /// character) are in line 1.
36 pub fn line(&self) -> usize {
40 /// One-based column number at which the error was detected.
42 /// The first character in the input and any characters immediately
43 /// following a newline character are in column 1.
45 /// Note that errors may occur in column 0, for example if a read from an IO
46 /// stream fails immediately following a previously read newline character.
47 pub fn column(&self) -> usize {
51 /// Categorizes the cause of this error.
53 /// - `Category::Io` - failure to read or write bytes on an IO stream
54 /// - `Category::Syntax` - input that is not syntactically valid JSON
55 /// - `Category::Data` - input data that is semantically incorrect
56 /// - `Category::Eof` - unexpected end of the input data
57 pub fn classify(&self) -> Category
{
59 ErrorCode
::Message(_
) => Category
::Data
,
60 ErrorCode
::Io(_
) => Category
::Io
,
61 ErrorCode
::EofWhileParsingList
62 | ErrorCode
::EofWhileParsingObject
63 | ErrorCode
::EofWhileParsingString
64 | ErrorCode
::EofWhileParsingValue
=> Category
::Eof
,
65 ErrorCode
::ExpectedColon
66 | ErrorCode
::ExpectedListCommaOrEnd
67 | ErrorCode
::ExpectedObjectCommaOrEnd
68 | ErrorCode
::ExpectedObjectOrArray
69 | ErrorCode
::ExpectedSomeIdent
70 | ErrorCode
::ExpectedSomeValue
71 | ErrorCode
::ExpectedSomeString
72 | ErrorCode
::InvalidEscape
73 | ErrorCode
::InvalidNumber
74 | ErrorCode
::NumberOutOfRange
75 | ErrorCode
::InvalidUnicodeCodePoint
76 | ErrorCode
::ControlCharacterWhileParsingString
77 | ErrorCode
::KeyMustBeAString
78 | ErrorCode
::LoneLeadingSurrogateInHexEscape
79 | ErrorCode
::TrailingComma
80 | ErrorCode
::TrailingCharacters
81 | ErrorCode
::UnexpectedEndOfHexEscape
82 | ErrorCode
::RecursionLimitExceeded
=> Category
::Syntax
,
86 /// Returns true if this error was caused by a failure to read or write
87 /// bytes on an IO stream.
88 pub fn is_io(&self) -> bool
{
89 self.classify() == Category
::Io
92 /// Returns true if this error was caused by input that was not
93 /// syntactically valid JSON.
94 pub fn is_syntax(&self) -> bool
{
95 self.classify() == Category
::Syntax
98 /// Returns true if this error was caused by input data that was
99 /// semantically incorrect.
101 /// For example, JSON containing a number is semantically incorrect when the
102 /// type being deserialized into holds a String.
103 pub fn is_data(&self) -> bool
{
104 self.classify() == Category
::Data
107 /// Returns true if this error was caused by prematurely reaching the end of
110 /// Callers that process streaming input may be interested in retrying the
111 /// deserialization once more data is available.
112 pub fn is_eof(&self) -> bool
{
113 self.classify() == Category
::Eof
117 /// Categorizes the cause of a `serde_json::Error`.
118 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
120 /// The error was caused by a failure to read or write bytes on an IO
124 /// The error was caused by input that was not syntactically valid JSON.
127 /// The error was caused by input data that was semantically incorrect.
129 /// For example, JSON containing a number is semantically incorrect when the
130 /// type being deserialized into holds a String.
133 /// The error was caused by prematurely reaching the end of the input data.
135 /// Callers that process streaming input may be interested in retrying the
136 /// deserialization once more data is available.
140 #[cfg_attr(feature = "cargo-clippy", allow(fallible_impl_from))]
141 impl From
<Error
> for io
::Error
{
142 /// Convert a `serde_json::Error` into an `io::Error`.
144 /// JSON syntax and data errors are turned into `InvalidData` IO errors.
145 /// EOF errors are turned into `UnexpectedEof` IO errors.
152 /// Json(serde_json::Error),
155 /// impl From<serde_json::Error> for MyError {
156 /// fn from(err: serde_json::Error) -> MyError {
157 /// use serde_json::error::Category;
158 /// match err.classify() {
159 /// Category::Io => {
160 /// MyError::Io(err.into())
162 /// Category::Syntax | Category::Data | Category::Eof => {
163 /// MyError::Json(err)
169 fn from(j
: Error
) -> Self {
170 if let ErrorCode
::Io(err
) = j
.err
.code
{
174 Category
::Io
=> unreachable
!(),
175 Category
::Syntax
| Category
::Data
=> io
::Error
::new(io
::ErrorKind
::InvalidData
, j
),
176 Category
::Eof
=> io
::Error
::new(io
::ErrorKind
::UnexpectedEof
, j
),
188 // Not public API. Should be pub(crate).
191 /// Catchall for syntax error messages
194 /// Some IO error occurred while serializing or deserializing.
197 /// EOF while parsing a list.
200 /// EOF while parsing an object.
201 EofWhileParsingObject
,
203 /// EOF while parsing a string.
204 EofWhileParsingString
,
206 /// EOF while parsing a JSON value.
207 EofWhileParsingValue
,
209 /// Expected this character to be a `':'`.
212 /// Expected this character to be either a `','` or a `']'`.
213 ExpectedListCommaOrEnd
,
215 /// Expected this character to be either a `','` or a `'}'`.
216 ExpectedObjectCommaOrEnd
,
218 /// Expected this character to be either a `'{'` or a `'['`.
219 ExpectedObjectOrArray
,
221 /// Expected to parse either a `true`, `false`, or a `null`.
224 /// Expected this character to start a JSON value.
227 /// Expected this character to start a JSON string.
230 /// Invalid hex escape code.
236 /// Number is bigger than the maximum value of its type.
239 /// Invalid unicode code point.
240 InvalidUnicodeCodePoint
,
242 /// Control character found while parsing a string.
243 ControlCharacterWhileParsingString
,
245 /// Object key is not a string.
248 /// Lone leading surrogate in hex escape.
249 LoneLeadingSurrogateInHexEscape
,
251 /// JSON has a comma after the last value in an array or map.
254 /// JSON has non-whitespace trailing characters after the value.
257 /// Unexpected end of hex excape.
258 UnexpectedEndOfHexEscape
,
260 /// Encountered nesting of JSON maps and arrays more than 128 layers deep.
261 RecursionLimitExceeded
,
265 // Not public API. Should be pub(crate).
267 pub fn syntax(code
: ErrorCode
, line
: usize, column
: usize) -> Self {
269 err
: Box
::new(ErrorImpl
{
277 // Not public API. Should be pub(crate).
279 // Update `eager_json` crate when this function changes.
281 pub fn io(error
: io
::Error
) -> Self {
283 err
: Box
::new(ErrorImpl
{
284 code
: ErrorCode
::Io(error
),
291 // Not public API. Should be pub(crate).
293 pub fn fix_position
<F
>(self, f
: F
) -> Self
295 F
: FnOnce(ErrorCode
) -> Error
,
297 if self.err
.line
== 0 {
305 impl Display
for ErrorCode
{
306 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
308 ErrorCode
::Message(ref msg
) => f
.write_str(msg
),
309 ErrorCode
::Io(ref err
) => Display
::fmt(err
, f
),
310 ErrorCode
::EofWhileParsingList
=> f
.write_str("EOF while parsing a list"),
311 ErrorCode
::EofWhileParsingObject
=> f
.write_str("EOF while parsing an object"),
312 ErrorCode
::EofWhileParsingString
=> f
.write_str("EOF while parsing a string"),
313 ErrorCode
::EofWhileParsingValue
=> f
.write_str("EOF while parsing a value"),
314 ErrorCode
::ExpectedColon
=> f
.write_str("expected `:`"),
315 ErrorCode
::ExpectedListCommaOrEnd
=> f
.write_str("expected `,` or `]`"),
316 ErrorCode
::ExpectedObjectCommaOrEnd
=> f
.write_str("expected `,` or `}`"),
317 ErrorCode
::ExpectedObjectOrArray
=> f
.write_str("expected `{` or `[`"),
318 ErrorCode
::ExpectedSomeIdent
=> f
.write_str("expected ident"),
319 ErrorCode
::ExpectedSomeValue
=> f
.write_str("expected value"),
320 ErrorCode
::ExpectedSomeString
=> f
.write_str("expected string"),
321 ErrorCode
::InvalidEscape
=> f
.write_str("invalid escape"),
322 ErrorCode
::InvalidNumber
=> f
.write_str("invalid number"),
323 ErrorCode
::NumberOutOfRange
=> f
.write_str("number out of range"),
324 ErrorCode
::InvalidUnicodeCodePoint
=> f
.write_str("invalid unicode code point"),
325 ErrorCode
::ControlCharacterWhileParsingString
=> {
326 f
.write_str("control character (\\u0000-\\u001F) found while parsing a string")
328 ErrorCode
::KeyMustBeAString
=> f
.write_str("key must be a string"),
329 ErrorCode
::LoneLeadingSurrogateInHexEscape
=> {
330 f
.write_str("lone leading surrogate in hex escape")
332 ErrorCode
::TrailingComma
=> f
.write_str("trailing comma"),
333 ErrorCode
::TrailingCharacters
=> f
.write_str("trailing characters"),
334 ErrorCode
::UnexpectedEndOfHexEscape
=> f
.write_str("unexpected end of hex escape"),
335 ErrorCode
::RecursionLimitExceeded
=> f
.write_str("recursion limit exceeded"),
340 impl error
::Error
for Error
{
341 fn description(&self) -> &str {
342 match self.err
.code
{
343 ErrorCode
::Io(ref err
) => error
::Error
::description(err
),
345 // If you want a better message, use Display::fmt or to_string().
351 fn cause(&self) -> Option
<&error
::Error
> {
352 match self.err
.code
{
353 ErrorCode
::Io(ref err
) => Some(err
),
359 impl Display
for Error
{
360 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
361 Display
::fmt(&*self.err
, f
)
365 impl Display
for ErrorImpl
{
366 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
368 Display
::fmt(&self.code
, f
)
372 "{} at line {} column {}",
373 self.code
, self.line
, self.column
379 // Remove two layers of verbosity from the debug representation. Humans often
380 // end up seeing this representation because it is what unwrap() shows.
381 impl Debug
for Error
{
382 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
385 "Error({:?}, line: {}, column: {})",
386 self.err
.code
.to_string(),
393 impl de
::Error
for Error
{
394 fn custom
<T
: Display
>(msg
: T
) -> Error
{
396 err
: Box
::new(ErrorImpl
{
397 code
: ErrorCode
::Message(msg
.to_string().into_boxed_str()),
404 fn invalid_type(unexp
: de
::Unexpected
, exp
: &de
::Expected
) -> Self {
405 if let de
::Unexpected
::Unit
= unexp
{
406 Error
::custom(format_args
!("invalid type: null, expected {}", exp
))
408 Error
::custom(format_args
!("invalid type: {}, expected {}", unexp
, exp
))
413 impl ser
::Error
for Error
{
414 fn custom
<T
: Display
>(msg
: T
) -> Error
{
416 err
: Box
::new(ErrorImpl
{
417 code
: ErrorCode
::Message(msg
.to_string().into_boxed_str()),