use alloc::string::{String, ToString};
use core::fmt;
use serde::de::DeserializeOwned;
use serde_json::Value as JsonValue;
use crate::error::Error;
use crate::options::Options;
use crate::value::Value;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum DeserializeError {
Repair(Error),
Json(String),
}
impl fmt::Display for DeserializeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DeserializeError::Repair(error) => write!(f, "repair failed: {error}"),
DeserializeError::Json(message) => write!(f, "deserialization failed: {message}"),
}
}
}
impl core::error::Error for DeserializeError {}
impl From<Error> for DeserializeError {
fn from(error: Error) -> Self {
DeserializeError::Repair(error)
}
}
pub fn deserialize<T: DeserializeOwned>(input: &str) -> Result<T, DeserializeError> {
deserialize_with(input, Options::all())
}
pub fn deserialize_with<T: DeserializeOwned>(
input: &str,
opts: Options,
) -> Result<T, DeserializeError> {
let repaired = crate::repair_with(input, opts)?;
serde_json::from_str(&repaired).map_err(|error| DeserializeError::Json(error.to_string()))
}
pub fn loads(input: &str) -> Result<JsonValue, DeserializeError> {
loads_with(input, Options::all())
}
pub fn loads_with(input: &str, opts: Options) -> Result<JsonValue, DeserializeError> {
let value = crate::parse_with(input, opts)?;
Ok(value.to_serde_json())
}
impl Value {
pub fn to_serde_json(&self) -> JsonValue {
match self {
Value::Null => JsonValue::Null,
Value::Bool(value) => JsonValue::Bool(*value),
Value::Number(number) => {
let text = number.as_str();
if let Ok(value) = text.parse::<i64>() {
JsonValue::from(value)
} else if let Ok(value) = text.parse::<u64>() {
JsonValue::from(value)
} else {
match text
.parse::<f64>()
.ok()
.and_then(serde_json::Number::from_f64)
{
Some(value) => JsonValue::Number(value),
None => JsonValue::String(String::from(text)),
}
}
}
Value::String(text) => JsonValue::String(text.clone()),
Value::Array(items) => {
JsonValue::Array(items.iter().map(Value::to_serde_json).collect())
}
Value::Object(members) => JsonValue::Object(
members
.iter()
.map(|(key, value)| (key.clone(), value.to_serde_json()))
.collect(),
),
}
}
pub fn from_serde_json(value: &JsonValue) -> Value {
match value {
JsonValue::Null => Value::Null,
JsonValue::Bool(value) => Value::Bool(*value),
JsonValue::Number(number) => {
Value::Number(crate::value::Number::from_normalized(number.to_string()))
}
JsonValue::String(text) => Value::String(text.clone()),
JsonValue::Array(items) => {
Value::Array(items.iter().map(Value::from_serde_json).collect())
}
JsonValue::Object(members) => Value::Object(
members
.iter()
.map(|(key, value)| (key.clone(), Value::from_serde_json(value)))
.collect(),
),
}
}
}