mirror of https://github.com/buster-so/buster.git
fix on chart config object
This commit is contained in:
parent
7111f9e110
commit
ec0524f83a
|
@ -152,35 +152,112 @@ impl<'de> Deserialize<'de> for ChartConfig {
|
||||||
|
|
||||||
// Helper function to create detailed error messages for deserialization failures
|
// Helper function to create detailed error messages for deserialization failures
|
||||||
fn detailed_deserialization_error<E: serde::de::Error>(chart_type: &str, err: &serde_json::Error) -> E {
|
fn detailed_deserialization_error<E: serde::de::Error>(chart_type: &str, err: &serde_json::Error) -> E {
|
||||||
match err.classify() {
|
|
||||||
serde_json::error::Category::Data => {
|
|
||||||
// Type mismatch or invalid value
|
|
||||||
let error_message = format!("{} config error: {}", chart_type, err);
|
|
||||||
|
|
||||||
// Extract the field path from the error message if possible
|
|
||||||
if let Some(field_name) = extract_field_from_error(err) {
|
|
||||||
E::custom(format!("{} config error at field '{}': {}", chart_type, field_name, err))
|
|
||||||
} else {
|
|
||||||
E::custom(error_message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serde_json::error::Category::Syntax | serde_json::error::Category::Io | serde_json::error::Category::Eof => {
|
|
||||||
// Other errors (shouldn't happen in this context)
|
|
||||||
E::custom(format!("{} config parse error: {}", chart_type, err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to extract field name from error message
|
|
||||||
fn extract_field_from_error(err: &serde_json::Error) -> Option<String> {
|
|
||||||
// Get the error message as a string
|
// Get the error message as a string
|
||||||
let err_msg = err.to_string();
|
let err_msg = err.to_string();
|
||||||
|
|
||||||
// Try to extract field path using common patterns in serde_json error messages
|
// Match different error patterns to extract field information
|
||||||
if let Some(start_idx) = err_msg.find("at key ") {
|
let detailed_error = match extract_detailed_error_info(&err_msg) {
|
||||||
if let Some(key_start) = err_msg[start_idx + 8..].find('"') {
|
Some((field_name, expected_type, found_type)) => {
|
||||||
if let Some(key_end) = err_msg[start_idx + 8 + key_start + 1..].find('"') {
|
// Complete type mismatch info available
|
||||||
let field = &err_msg[start_idx + 8 + key_start + 1..start_idx + 8 + key_start + 1 + key_end];
|
format!(
|
||||||
|
"{} config error: field '{}' has invalid type: {}, expected {}",
|
||||||
|
chart_type, field_name, found_type, expected_type
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Try to at least extract the field name
|
||||||
|
if let Some(field_name) = extract_field_from_error(&err_msg) {
|
||||||
|
format!("{} config error at field '{}': {}", chart_type, field_name, err)
|
||||||
|
} else {
|
||||||
|
format!("{} config error: {}", chart_type, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
E::custom(detailed_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to extract detailed type mismatch information
|
||||||
|
fn extract_detailed_error_info(err_msg: &str) -> Option<(String, String, String)> {
|
||||||
|
// Pattern for serde "invalid type" errors: "invalid type: X, expected Y at ..."
|
||||||
|
if err_msg.starts_with("invalid type:") {
|
||||||
|
// Extract expected and found types
|
||||||
|
let parts: Vec<&str> = err_msg.split(", expected ").collect();
|
||||||
|
if parts.len() >= 2 {
|
||||||
|
let found_type = parts[0].replace("invalid type: ", "").trim().to_string();
|
||||||
|
|
||||||
|
// Extract field path and expected type
|
||||||
|
let remaining = parts[1];
|
||||||
|
let field_parts: Vec<&str> = remaining.split(" at ").collect();
|
||||||
|
let expected_type = field_parts[0].trim().to_string();
|
||||||
|
|
||||||
|
// Try to extract field name
|
||||||
|
if field_parts.len() >= 2 {
|
||||||
|
if let Some(field_name) = extract_field_path(field_parts[1]) {
|
||||||
|
return Some((field_name, expected_type, found_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we couldn't extract field but have types, use a placeholder
|
||||||
|
return Some(("unknown_field".to_string(), expected_type, found_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to extract field path from location info
|
||||||
|
fn extract_field_path(location_info: &str) -> Option<String> {
|
||||||
|
// Try to extract field name from different patterns
|
||||||
|
|
||||||
|
// Pattern: key `field_name` at line X column Y
|
||||||
|
if let Some(start_idx) = location_info.find("key `") {
|
||||||
|
if let Some(end_idx) = location_info[start_idx + 5..].find('`') {
|
||||||
|
return Some(location_info[start_idx + 5..start_idx + 5 + end_idx].to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern: at key "field_name"
|
||||||
|
if let Some(start_idx) = location_info.find("at key \"") {
|
||||||
|
if let Some(end_idx) = location_info[start_idx + 8..].find('"') {
|
||||||
|
return Some(location_info[start_idx + 8..start_idx + 8 + end_idx].to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern: "field_name":
|
||||||
|
if let Some(start_idx) = location_info.find('"') {
|
||||||
|
if let Some(end_idx) = location_info[start_idx + 1..].find('"') {
|
||||||
|
return Some(location_info[start_idx + 1..start_idx + 1 + end_idx].to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to extract field name from error message
|
||||||
|
fn extract_field_from_error(err_msg: &str) -> Option<String> {
|
||||||
|
// Try multiple patterns to extract field names
|
||||||
|
|
||||||
|
// Pattern: key `field_name` at line X column Y
|
||||||
|
if let Some(start_idx) = err_msg.find("key `") {
|
||||||
|
if let Some(end_idx) = err_msg[start_idx + 5..].find('`') {
|
||||||
|
return Some(err_msg[start_idx + 5..start_idx + 5 + end_idx].to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern: at key "field_name"
|
||||||
|
if let Some(start_idx) = err_msg.find("at key \"") {
|
||||||
|
if let Some(end_idx) = err_msg[start_idx + 8..].find('"') {
|
||||||
|
return Some(err_msg[start_idx + 8..start_idx + 8 + end_idx].to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern: "field_name":
|
||||||
|
if let Some(start_idx) = err_msg.find('"') {
|
||||||
|
if let Some(end_idx) = err_msg[start_idx + 1..].find('"') {
|
||||||
|
let field = &err_msg[start_idx + 1..start_idx + 1 + end_idx];
|
||||||
|
// Avoid capturing things that aren't likely field names
|
||||||
|
if !field.contains(' ') && field.len() > 0 && field.len() < 50 {
|
||||||
return Some(field.to_string());
|
return Some(field.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +285,7 @@ pub struct BaseChartConfig {
|
||||||
pub grid_lines: Option<bool>,
|
pub grid_lines: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(alias = "show_legend_headline")]
|
#[serde(alias = "show_legend_headline")]
|
||||||
pub show_legend_headline: Option<String>,
|
pub show_legend_headline: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(alias = "goal_lines")]
|
#[serde(alias = "goal_lines")]
|
||||||
pub goal_lines: Option<Vec<GoalLine>>,
|
pub goal_lines: Option<Vec<GoalLine>>,
|
||||||
|
@ -367,7 +444,7 @@ pub struct BarLineChartConfig {
|
||||||
pub bar_layout: Option<String>,
|
pub bar_layout: Option<String>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(alias = "bar_sort_by")]
|
#[serde(alias = "bar_sort_by")]
|
||||||
pub bar_sort_by: Option<String>,
|
pub bar_sort_by: Option<Vec<String>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(alias = "bar_group_type")]
|
#[serde(alias = "bar_group_type")]
|
||||||
pub bar_group_type: Option<String>,
|
pub bar_group_type: Option<String>,
|
||||||
|
|
Loading…
Reference in New Issue