#![deny(missing_docs)]
mod balanced;
mod commas;
mod fences;
pub use balanced::extract_balanced;
pub use commas::strip_trailing_commas;
pub use fences::strip_fences;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum RepairError {
#[cfg(feature = "serde")]
#[error("could not parse JSON after repair: {source}")]
Parse {
#[source]
source: serde_json::Error,
repaired: String,
},
#[error("no JSON object or array found in input")]
NoJsonFound,
}
pub fn repair(input: &str) -> String {
let unfenced = strip_fences(input);
let extracted = extract_balanced(&unfenced)
.unwrap_or(unfenced.trim())
.to_string();
strip_trailing_commas(&extracted)
}
#[cfg(feature = "serde")]
pub fn parse<T>(input: &str) -> Result<T, RepairError>
where
T: serde::de::DeserializeOwned,
{
let unfenced = strip_fences(input);
let extracted = match extract_balanced(&unfenced) {
Some(s) => s.to_string(),
None => return Err(RepairError::NoJsonFound),
};
let cleaned = strip_trailing_commas(&extracted);
serde_json::from_str::<T>(&cleaned).map_err(|source| RepairError::Parse {
source,
repaired: cleaned,
})
}
#[cfg(feature = "serde")]
pub fn parse_strict<T>(input: &str) -> Result<T, RepairError>
where
T: serde::de::DeserializeOwned,
{
serde_json::from_str::<T>(input).map_err(|source| RepairError::Parse {
source,
repaired: input.to_string(),
})
}