use serde::de::DeserializeOwned;
use serde_json::{Value, error::Category};
use crate::{
JsonDecodeError, JsonDecodeOptions, JsonTopLevelKind,
lenient_json_normalizer::LenientJsonNormalizer,
};
#[derive(Debug, Clone, Default)]
pub struct LenientJsonDecoder {
normalizer: LenientJsonNormalizer,
}
impl LenientJsonDecoder {
#[must_use]
pub const fn new(options: JsonDecodeOptions) -> Self {
Self {
normalizer: LenientJsonNormalizer::new(options),
}
}
#[must_use]
pub const fn options(&self) -> &JsonDecodeOptions {
self.normalizer.options()
}
pub fn decode<T>(&self, input: &str) -> Result<T, JsonDecodeError>
where
T: DeserializeOwned,
{
let normalized = self.normalizer.normalize(input)?;
Self::deserialize_normalized(normalized.as_ref(), normalized.len())
}
pub fn decode_object<T>(&self, input: &str) -> Result<T, JsonDecodeError>
where
T: DeserializeOwned,
{
self.decode_with_top_level(input, JsonTopLevelKind::Object)
}
pub fn decode_array<T>(&self, input: &str) -> Result<Vec<T>, JsonDecodeError>
where
T: DeserializeOwned,
{
self.decode_with_top_level(input, JsonTopLevelKind::Array)
}
pub fn decode_value(&self, input: &str) -> Result<Value, JsonDecodeError> {
let (value, _) = self.parse_input_as_value(input)?;
Ok(value)
}
fn parse_input_as_value(&self, input: &str) -> Result<(Value, usize), JsonDecodeError> {
let normalized = self.normalizer.normalize(input)?;
let input_bytes = normalized.len();
let value = Self::parse_value(normalized.as_ref())?;
Ok((value, input_bytes))
}
fn decode_with_top_level<T>(
&self,
input: &str,
expected: JsonTopLevelKind,
) -> Result<T, JsonDecodeError>
where
T: DeserializeOwned,
{
let (value, input_bytes) = self.parse_input_as_value(input)?;
Self::ensure_top_level_from_value(&value, expected)?;
Self::deserialize_value(value, input_bytes)
}
fn parse_value(normalized: &str) -> Result<Value, JsonDecodeError> {
serde_json::from_str(normalized)
.map_err(|error| JsonDecodeError::invalid_json(error, Some(normalized.len())))
}
fn ensure_top_level_from_value(
value: &Value,
expected: JsonTopLevelKind,
) -> Result<(), JsonDecodeError> {
let actual = JsonTopLevelKind::of(value);
if actual != expected {
return Err(JsonDecodeError::unexpected_top_level(expected, actual));
}
Ok(())
}
fn deserialize_normalized<T>(normalized: &str, input_bytes: usize) -> Result<T, JsonDecodeError>
where
T: DeserializeOwned,
{
serde_json::from_str(normalized).map_err(|error| Self::map_decode_error(error, input_bytes))
}
fn deserialize_value<T>(value: Value, input_bytes: usize) -> Result<T, JsonDecodeError>
where
T: DeserializeOwned,
{
serde_json::from_value(value)
.map_err(|error| JsonDecodeError::deserialize(error, Some(input_bytes)))
}
fn map_decode_error(error: serde_json::Error, input_bytes: usize) -> JsonDecodeError {
match error.classify() {
Category::Data => JsonDecodeError::deserialize(error, Some(input_bytes)),
Category::Io | Category::Syntax | Category::Eof => {
JsonDecodeError::invalid_json(error, Some(input_bytes))
}
}
}
}