use schemars::JsonSchema;
use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize};
use serde_json::Value;
use std::{
ops::{Deref, DerefMut},
str::FromStr,
};
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[repr(transparent)]
pub struct Json<T: DeserializeOwned = Value>(pub T);
#[allow(clippy::module_name_repetitions)]
pub trait ToJson {
type Target: Serialize + DeserializeOwned;
fn to_json(self) -> Json<Self::Target>;
}
impl FromStr for Json {
type Err = serde_json::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(serde_json::from_str(s)?))
}
}
impl From<Value> for Json {
fn from(value: Value) -> Self {
Self(value)
}
}
impl<T: Serialize + DeserializeOwned> ToJson for T {
type Target = T;
fn to_json(self) -> Json<T> {
Json(self)
}
}
impl<T: Serialize + DeserializeOwned> Serialize for Json<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::Error;
if std::any::type_name::<S::Error>() == std::any::type_name::<rbs::Error>() {
serializer.serialize_newtype_struct(
"Json",
&serde_json::to_string(&self.0).map_err(|e| Error::custom(e.to_string()))?,
)
} else {
self.0.serialize(serializer)
}
}
}
impl<'de, T: Serialize + DeserializeOwned> Deserialize<'de> for Json<T> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
if std::any::type_name::<D::Error>() == std::any::type_name::<rbs::Error>() {
let mut v = rbs::Value::deserialize(deserializer)?;
if let rbs::Value::Ext(_ty, buf) = v {
v = *buf;
}
let js;
if let rbs::Value::Binary(buf) = v {
js = String::from_utf8(buf).map_err(|e| Error::custom(e.to_string()))?;
} else if let rbs::Value::String(buf) = v {
js = buf;
} else {
js = v.to_string();
}
Ok(Self(
serde_json::from_str(&js).map_err(|e| Error::custom(e.to_string()))?,
))
} else {
Ok(Self(T::deserialize(deserializer)?))
}
}
}
impl<T: Serialize + DeserializeOwned> Deref for Json<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Serialize + DeserializeOwned> DerefMut for Json<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: Serialize + DeserializeOwned + Default> Default for Json<T> {
fn default() -> Self {
Self(T::default())
}
}
#[cfg(feature = "schema")]
impl<T: Serialize + DeserializeOwned + JsonSchema> schemars::JsonSchema for Json<T> {
fn schema_name() -> String {
T::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
T::json_schema(gen)
}
}