Skip to content

Commit 5d363cc

Browse files
authored
Improve serde error output (#982)
In our tests using the serde impl on `Url`, we found that failing URL serialization says the inverse of what it should say. ```toml [project] name = "foo" version = "0.0.0" dependencies = [ "tqdm ==4.66.0", ] [tool.uv.sources] tqdm = { url = "§invalid#+#*Ä" } ``` ``` error: Failed to parse: `pyproject.toml` Caused by: TOML parse error at line 10, column 16 | 10 | tqdm = { url = "§invalid#+#*Ä" } | ^^^^^^^^^^^^^^^^^ invalid value: string "§invalid#+#*Ä", expected relative URL without a base ``` It says that expected a relative URL without a base, when this was the unexpected input that caused the error. Using `serde::de::Error::custom` oder `serde::de::Error::invalid_value` improves the error message: ``` error: TOML parse error at line 8, column 16 | 8 | tqdm = { url = "§invalid#+#*Ä" } | ^^^^^^^^^^^^^^^^^ relative URL without a base: "§invalid#+#*Ä" ```
1 parent 30e6258 commit 5d363cc

File tree

2 files changed

+22
-10
lines changed

2 files changed

+22
-10
lines changed

url/src/lib.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -2700,7 +2700,7 @@ impl Url {
27002700
where
27012701
D: serde::Deserializer<'de>,
27022702
{
2703-
use serde::de::{Deserialize, Error, Unexpected};
2703+
use serde::de::{Deserialize, Error};
27042704
let (
27052705
serialization,
27062706
scheme_end,
@@ -2726,10 +2726,8 @@ impl Url {
27262726
fragment_start,
27272727
};
27282728
if cfg!(debug_assertions) {
2729-
url.check_invariants().map_err(|reason| {
2730-
let reason: &str = &reason;
2731-
Error::invalid_value(Unexpected::Other("value"), &reason)
2732-
})?
2729+
url.check_invariants()
2730+
.map_err(|reason| Error::custom(reason))?
27332731
}
27342732
Ok(url)
27352733
}
@@ -2942,7 +2940,7 @@ impl<'de> serde::Deserialize<'de> for Url {
29422940
where
29432941
D: serde::Deserializer<'de>,
29442942
{
2945-
use serde::de::{Error, Unexpected, Visitor};
2943+
use serde::de::{Error, Visitor};
29462944

29472945
struct UrlVisitor;
29482946

@@ -2957,10 +2955,7 @@ impl<'de> serde::Deserialize<'de> for Url {
29572955
where
29582956
E: Error,
29592957
{
2960-
Url::parse(s).map_err(|err| {
2961-
let err_s = format!("{}", err);
2962-
Error::invalid_value(Unexpected::Str(s), &err_s.as_str())
2963-
})
2958+
Url::parse(s).map_err(|err| Error::custom(format!("{}: {:?}", err, s)))
29642959
}
29652960
}
29662961

url/tests/unit.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1362,3 +1362,20 @@ fn issue_974() {
13621362
let _ = url::quirks::set_port(&mut url, "\u{0000}9000");
13631363
assert_eq!(url.port(), Some(8000));
13641364
}
1365+
1366+
#[cfg(feature = "serde")]
1367+
#[test]
1368+
fn serde_error_message() {
1369+
use serde::Deserialize;
1370+
#[derive(Debug, Deserialize)]
1371+
#[allow(dead_code)]
1372+
struct TypeWithUrl {
1373+
url: Url,
1374+
}
1375+
1376+
let err = serde_json::from_str::<TypeWithUrl>(r#"{"url": "§invalid#+#*Ä"}"#).unwrap_err();
1377+
assert_eq!(
1378+
err.to_string(),
1379+
r#"relative URL without a base: "§invalid#+#*Ä" at line 1 column 25"#
1380+
);
1381+
}

0 commit comments

Comments
 (0)