mirror of
https://github.com/Xevion/banner.git
synced 2025-12-06 05:14:26 -06:00
fix: improve json error handling, make email_address optional
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -193,6 +193,7 @@ dependencies = [
|
|||||||
"reqwest-middleware",
|
"reqwest-middleware",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_path_to_error",
|
||||||
"serenity",
|
"serenity",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"thiserror 2.0.16",
|
"thiserror 2.0.16",
|
||||||
|
|||||||
@@ -43,5 +43,6 @@ tracing-subscriber = { version = "0.3.20", features = ["env-filter", "json"] }
|
|||||||
url = "2.5"
|
url = "2.5"
|
||||||
governor = "0.10.1"
|
governor = "0.10.1"
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
|
serde_path_to_error = "0.1.17"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
//! JSON parsing utilities for the Banner API client.
|
//! JSON parsing utilities for the Banner API client.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
/// Attempt to parse JSON and, on failure, include a contextual snippet of the
|
/// Attempt to parse JSON and, on failure, include a contextual snippet of the
|
||||||
/// line where the error occurred. This prevents dumping huge JSON bodies to logs.
|
/// line where the error occurred. This prevents dumping huge JSON bodies to logs.
|
||||||
pub fn parse_json_with_context<T: serde::de::DeserializeOwned>(body: &str) -> Result<T> {
|
pub fn parse_json_with_context<T: serde::de::DeserializeOwned>(body: &str) -> Result<T> {
|
||||||
match serde_json::from_str::<T>(body) {
|
let jd = &mut serde_json::Deserializer::from_str(body);
|
||||||
|
match serde_path_to_error::deserialize(jd) {
|
||||||
Ok(value) => Ok(value),
|
Ok(value) => Ok(value),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let (line, column) = (err.line(), err.column());
|
let inner_err = err.inner();
|
||||||
// let snippet = build_error_snippet(body, line, column, 80);
|
let (line, column) = (inner_err.line(), inner_err.column());
|
||||||
Err(anyhow::anyhow!("{err} at line {line}, column {column}",))
|
let snippet = build_error_snippet(body, line, column, 20);
|
||||||
|
let path = err.path().to_string();
|
||||||
|
|
||||||
|
let msg = inner_err.to_string();
|
||||||
|
let loc = format!(" at line {line} column {column}");
|
||||||
|
let msg_without_loc = msg.strip_suffix(&loc).unwrap_or(&msg).to_string();
|
||||||
|
|
||||||
|
let mut final_err = String::new();
|
||||||
|
if !path.is_empty() && path != "." {
|
||||||
|
final_err.push_str(&format!("for path '{}' ", path));
|
||||||
|
}
|
||||||
|
final_err.push_str(&format!(
|
||||||
|
"({msg_without_loc}) at line {line} column {column}"
|
||||||
|
));
|
||||||
|
final_err.push_str(&format!("\n{snippet}"));
|
||||||
|
|
||||||
|
Err(anyhow::anyhow!(final_err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ pub struct FacultyItem {
|
|||||||
#[serde(deserialize_with = "deserialize_string_to_u32")]
|
#[serde(deserialize_with = "deserialize_string_to_u32")]
|
||||||
pub course_reference_number: u32, // CRN, e.g 27294
|
pub course_reference_number: u32, // CRN, e.g 27294
|
||||||
pub display_name: String, // "LastName, FirstName"
|
pub display_name: String, // "LastName, FirstName"
|
||||||
pub email_address: String, // e.g. FirstName.LastName@utsaedu
|
pub email_address: Option<String>, // e.g. FirstName.LastName@utsaedu
|
||||||
pub primary_indicator: bool,
|
pub primary_indicator: bool,
|
||||||
pub term: String, // e.g "202420"
|
pub term: String, // e.g "202420"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user