use super::value::Value;
use crate::json::key::{self, Key};
use crate::json::object_vec::ObjectAsVec;
use crate::{Element, Property};
use serde::de::{Deserialize, DeserializeSeed, MapAccess, SeqAccess, Visitor};
use std::borrow::Cow;
#[derive(Clone, Default)]
pub(crate) struct DeserializationContext<'x, P: Property, E: Element> {
parent_key: Option<&'x Key<'x, P>>,
phantom: std::marker::PhantomData<E>,
}
impl<'de, P: Property, E: Element<Property = P>> Deserialize<'de> for Value<'de, P, E> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
DeserializationContext {
parent_key: None,
phantom: std::marker::PhantomData,
}
.deserialize(deserializer)
}
}
impl<'de, 'x, P: Property, E: Element<Property = P>> DeserializeSeed<'de>
for DeserializationContext<'x, P, E>
{
type Value = Value<'de, P, E>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(ContextualVisitor { context: &self })
}
}
struct ContextualVisitor<'x, P: Property, E: Element> {
context: &'x DeserializationContext<'x, P, E>,
}
impl<'de, 'x, P: Property, E: Element<Property = P>> Visitor<'de> for ContextualVisitor<'x, P, E> {
type Value = Value<'de, P, E>;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("any valid JSON value")
}
#[inline]
fn visit_bool<ERR>(self, value: bool) -> Result<Value<'de, P, E>, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Bool(value))
}
#[inline]
fn visit_i64<ERR>(self, value: i64) -> Result<Value<'de, P, E>, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number(value.into()))
}
#[inline]
fn visit_u64<ERR>(self, value: u64) -> Result<Value<'de, P, E>, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number(value.into()))
}
#[inline]
fn visit_f64<ERR>(self, value: f64) -> Result<Value<'de, P, E>, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number(value.into()))
}
#[inline]
fn visit_string<ERR>(self, v: String) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
if let Some(element) = self
.context
.parent_key
.and_then(|key| E::try_parse::<P>(key, &v))
{
Ok(Value::Element(element))
} else {
Ok(Value::Str(Cow::Owned(v)))
}
}
#[inline]
fn visit_str<ERR>(self, v: &str) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
if let Some(element) = self
.context
.parent_key
.and_then(|key| E::try_parse::<P>(key, v))
{
Ok(Value::Element(element))
} else {
Ok(Value::Str(Cow::Owned(v.to_owned())))
}
}
#[inline]
fn visit_borrowed_str<ERR>(self, v: &'de str) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
if let Some(element) = self
.context
.parent_key
.and_then(|key| E::try_parse::<P>(key, v))
{
Ok(Value::Element(element))
} else {
Ok(Value::Str(Cow::Borrowed(v)))
}
}
#[inline]
fn visit_none<ERR>(self) -> Result<Value<'de, P, E>, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Null)
}
#[inline]
fn visit_i8<ERR>(self, v: i8) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as i64).into()))
}
#[inline]
fn visit_i16<ERR>(self, v: i16) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as i64).into()))
}
#[inline]
fn visit_i32<ERR>(self, v: i32) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as i64).into()))
}
#[inline]
fn visit_u8<ERR>(self, v: u8) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as u64).into()))
}
#[inline]
fn visit_u16<ERR>(self, v: u16) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as u64).into()))
}
#[inline]
fn visit_u32<ERR>(self, v: u32) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as u64).into()))
}
#[inline]
fn visit_f32<ERR>(self, v: f32) -> Result<Self::Value, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Number((v as f64).into()))
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Value<'de, P, E>, D::Error>
where
D: serde::Deserializer<'de>,
{
DeserializationContext {
parent_key: self.context.parent_key,
phantom: std::marker::PhantomData,
}
.deserialize(deserializer)
}
#[inline]
fn visit_unit<ERR>(self) -> Result<Value<'de, P, E>, ERR>
where
ERR: serde::de::Error,
{
Ok(Value::Null)
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<Value<'de, P, E>, V::Error>
where
V: SeqAccess<'de>,
{
let mut vec = Vec::with_capacity(visitor.size_hint().unwrap_or(0));
while let Some(elem) = visitor.next_element_seed(DeserializationContext {
parent_key: self.context.parent_key,
phantom: std::marker::PhantomData,
})? {
vec.push(elem);
}
Ok(Value::Array(vec))
}
#[inline]
fn visit_map<V>(self, mut visitor: V) -> Result<Value<'de, P, E>, V::Error>
where
V: MapAccess<'de>,
{
let mut values = Vec::with_capacity(visitor.size_hint().unwrap_or(0));
while let Some(key) = visitor.next_key_seed(key::DeserializationContext {
parent_key: self.context.parent_key,
})? {
let value = visitor.next_value_seed(DeserializationContext {
parent_key: Some(&key),
phantom: std::marker::PhantomData,
})?;
values.push((key, value));
}
Ok(Value::Object(ObjectAsVec(values)))
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use crate::{Null, Value};
#[test]
fn deserialize_json_test() {
let json_obj = r#"
{
"bool": true,
"string_key": "string_val",
"float": 1.23,
"i64": -123,
"u64": 123
}
"#;
let val: Value<'_, Null, Null> = serde_json::from_str(json_obj).unwrap();
assert_eq!(val.get("bool"), &Value::Bool(true));
assert_eq!(
val.get("string_key"),
&Value::Str(Cow::Borrowed("string_val"))
);
assert_eq!(val.get("float"), &Value::Number(1.23.into()));
assert_eq!(val.get("i64"), &Value::Number((-123i64).into()));
assert_eq!(val.get("u64"), &Value::Number(123u64.into()));
}
#[test]
fn deserialize_json_allow_escaped_strings_in_values() {
let json_obj = r#"
{
"bool": true,
"string_key": "string\"_val",
"u64": 123
}
"#;
let val: Value<'_, Null, Null> = serde_json::from_str(json_obj).unwrap();
assert_eq!(val.get("bool"), &Value::Bool(true));
assert_eq!(
val.get("string_key"),
&Value::Str(Cow::Borrowed("string\"_val"))
);
}
}