use serde::Serialize;
use serde_json::value::Value as Json;
use crate::context::Context;
use crate::error::RenderError;
use crate::helpers::HelperDef;
use crate::json::value::ScopedJson;
use crate::registry::Registry;
use crate::render::{Helper, RenderContext};
#[derive(Clone, Copy)]
pub struct JsonHelper;
impl HelperDef for JsonHelper {
fn call_inner<'reg: 'rc, 'rc>(
&self,
h: &Helper<'rc>,
_: &'reg Registry<'reg>,
_: &'rc Context,
_: &mut RenderContext<'reg, 'rc>,
) -> Result<ScopedJson<'rc>, RenderError> {
let value = h
.param(0)
.ok_or_else(|| RenderError::new("Param not found for helper \"json\""))?
.value();
if let None = h.param(1) {
return Ok(Json::String(value.to_string()).into());
}
let indent = match h.param(1).unwrap().value().as_str() {
None => Err(RenderError::new(
"Param invalid for helper \"json\": indent must be string",
)),
Some(indent) => Ok(indent.as_bytes()),
}?;
let formatter = serde_json::ser::PrettyFormatter::with_indent(indent);
let mut buf = Vec::new();
let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter);
value.serialize(&mut ser).unwrap();
Ok(match String::from_utf8(buf) {
Ok(js) => Json::String(js).into(),
Err(_) => Json::Null.into(),
})
}
}
pub static JSON_HELPER: JsonHelper = JsonHelper;
#[cfg(test)]
mod test {
#[test]
fn test_json() {
assert_renders![
(r##"{{ json "foo" }}"##, r##""foo""##),
(r##"{{ json this }}"##, r##"{"test":5}"##),
(r##"{{ json this " " }}"##, "{\n \"test\": 5\n}"),
@&json!({
"test": 5
}),
];
}
}