liquid_json/
liquid_json_value.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{liquid_json::LiquidJson, Error};
4
5#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq)]
6/// A Liquid JSON value that implements Serialize/Deserialize.
7#[must_use]
8pub struct LiquidJsonValue(
9    #[serde(serialize_with = "ser_with", deserialize_with = "deser_with")] LiquidJson,
10);
11
12impl LiquidJsonValue {
13    /// Create a new Liquid JSON value from a JSON value.
14    pub fn new(raw_template: serde_json::Value) -> Self {
15        LiquidJsonValue(LiquidJson::new(raw_template))
16    }
17    /// Render the JSON template with the given data.
18    pub fn render(&self, data: &serde_json::Value) -> Result<serde_json::Value, Error> {
19        self.0.render(data)
20    }
21
22    /// Get the inner [LiquidJson] value.
23    pub fn inner(&self) -> &LiquidJson {
24        &self.0
25    }
26
27    /// Get the unrendered template as a [serde_json::Value].
28    pub fn as_json(&self) -> &serde_json::Value {
29        self.0.as_json()
30    }
31}
32
33impl From<serde_json::Value> for LiquidJsonValue {
34    fn from(value: serde_json::Value) -> Self {
35        LiquidJsonValue::new(value)
36    }
37}
38
39fn ser_with<S>(tpl: &LiquidJson, s: S) -> Result<S::Ok, S::Error>
40where
41    S: serde::Serializer,
42{
43    tpl.raw_template.serialize(s)
44}
45
46fn deser_with<'de, D>(deserializer: D) -> Result<LiquidJson, D::Error>
47where
48    D: serde::de::Deserializer<'de>,
49{
50    let raw_template = serde_json::Value::deserialize(deserializer)?;
51    Ok(LiquidJson::new(raw_template))
52}
53#[cfg(test)]
54mod tests {
55    use ::serde::{Deserialize, Serialize};
56    use rstest::rstest;
57    use serde_json::{json, Value};
58
59    use super::*;
60    use anyhow::Result;
61
62    #[derive(Serialize, Deserialize, Debug, PartialEq)]
63    struct TestSerde {
64        inner_liquid: LiquidJsonValue,
65    }
66
67    #[rstest]
68    #[case(json!({"inner_liquid":"{{myval}}"}), json!({"myval": 5}), json!(5))]
69    #[case(json!({"inner_liquid":{"key":"{{myval}}"}}), json!({"myval": 5}), json!({"key":5}))]
70    #[case(json!({"inner_liquid":{"key":"{{myval}}"}}), json!({"myval": {"deeper":10}}), json!({"key":{"deeper":10}}))]
71    fn serde(#[case] from_json: Value, #[case] data: Value, #[case] expected: Value) -> Result<()> {
72        let deser: TestSerde = serde_json::from_value(from_json.clone())?;
73        let actual = deser.inner_liquid.render(&data)?;
74        assert_eq!(actual, expected);
75        let to_json = serde_json::to_value(deser)?;
76        assert_eq!(to_json, from_json);
77        Ok(())
78    }
79}