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> {
Ok(crate::parse_with(input, opts)?.into())
}
impl Value {
pub fn to_serde_json(&self) -> JsonValue {
JsonValue::from(self.clone())
}
pub fn from_serde_json(value: &JsonValue) -> Value {
Value::from(value.clone())
}
}
impl From<Value> for JsonValue {
fn from(value: Value) -> Self {
match value {
Value::Null => JsonValue::Null,
Value::Bool(value) => JsonValue::Bool(value),
Value::Number(number) => number_to_json(number),
Value::String(text) => JsonValue::String(text),
Value::Array(items) => JsonValue::Array(items.into_iter().map(Into::into).collect()),
Value::Object(members) => JsonValue::Object(
members
.into_iter()
.map(|(key, value)| (key, value.into()))
.collect(),
),
}
}
}
impl From<JsonValue> for Value {
fn from(value: JsonValue) -> Self {
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),
JsonValue::Array(items) => Value::Array(items.into_iter().map(Into::into).collect()),
JsonValue::Object(members) => Value::Object(
members
.into_iter()
.map(|(key, value)| (key, value.into()))
.collect(),
),
}
}
}
fn number_to_json(number: crate::value::Number) -> JsonValue {
use crate::value::Classified;
match number.classify() {
Some(Classified::I64(value)) => JsonValue::from(value),
Some(Classified::U64(value)) => JsonValue::from(value),
Some(Classified::F64(value)) => JsonValue::from(value),
None => JsonValue::String(number.into_string()),
}
}