You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
obws/src/serde/json_string.rs

102 lines
2.4 KiB
Rust

use std::{fmt, marker::PhantomData};
use serde::{
de::{self, DeserializeOwned, Deserializer, Visitor},
ser::{self, Serialize, Serializer},
};
#[derive(Debug, thiserror::Error)]
enum Error {
#[error("failed deserializing JSON string")]
InvalidJson(#[source] serde_json::Error),
}
pub fn serialize<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
let json = serde_json::to_string(value).map_err(ser::Error::custom)?;
serializer.serialize_str(&json)
}
#[allow(dead_code)]
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: DeserializeOwned,
{
deserializer.deserialize_str(JsonStringVisitor(PhantomData))
}
struct JsonStringVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for JsonStringVisitor<T>
where
T: DeserializeOwned,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("string value that contains JSON")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
serde_json::from_str(v).map_err(|e| de::Error::custom(Error::InvalidJson(e)))
}
}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
use serde_test::{assert_de_tokens_error, assert_tokens, Token};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Inner {
value: u32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct SimpleStruct {
#[serde(with = "super")]
inner: Inner,
}
#[test]
fn roundtrip() {
assert_tokens(
&SimpleStruct {
inner: Inner { value: 5 },
},
&[
Token::Struct {
name: "SimpleStruct",
len: 1,
},
Token::Str("inner"),
Token::Str(r#"{"value":5}"#),
Token::StructEnd,
],
)
}
#[test]
fn deser() {
assert_de_tokens_error::<SimpleStruct>(
&[
Token::Struct {
name: "SimpleStruct",
len: 1,
},
Token::Str("inner"),
Token::Str(""),
Token::StructEnd,
],
"failed deserializing JSON string",
);
}
}