从 json 数据渲染 scriban 模板
Render scriban template from json data
我想使用 ExpandoObject
或可以从 JSON 字符串生成的任何其他数据类型呈现 Scriban 模板:
var json = "....";
var dyn = JsonConvert.DeserializeObject<ExpandoObject>(json);
var template = Scriban.Template.Parse("Hello {{ data.foo }}!");
var result = template.Render(dyn);
Scriban 不适用于 ExpandoObject
s,因为它们被解析为 { key = '', value = '' }
对象的列表。在我的用例中,声明数据类型不是一个选项,因为 JSON 模式不是先验的。
将 ExpandoObject 转换为动态显示与直接使用 ExpandoObject
相同的行为。
我尝试将 JSON 反序列化为 dynamic
,这会导致异常:
System.Reflection.TargetParameterCountException: "Parameter count mismatch."
我能否以某种方式转换数据或配置 Scriban 以呈现动态数据?
如果你有一个简单的对象,你可以尝试这样的事情。
var json = "{\"Phone\":\"555000000\",\"Name\":\"Maia\"}";
var scriptObject = new Scriban.Runtime.ScriptObject();
var data = JsonConvert.DeserializeObject<ExpandoObject>(json);
foreach (var prop in data)
{
scriptObject.Add(prop.Key, prop.Value);
}
var templateCtx = new Scriban.TemplateContext();
templateCtx.PushGlobal(scriptObject);
var template = Scriban.Template.Parse("Hello {{Name}}");
var result = template.Render(templateCtx); // result will be "Hello Maia"
根据之前的回答,这是复杂对象的解决方案:
public static class ScribanRenderer
{
public static string RenderJson(string json, string content)
{
var expando = JsonConvert.DeserializeObject<ExpandoObject>(json);
var sObject = BuildScriptObject(expando);
var templateCtx = new Scriban.TemplateContext();
templateCtx.PushGlobal(sObject);
var template = Scriban.Template.Parse(content);
var result = template.Render(templateCtx);
return result;
}
private static ScriptObject BuildScriptObject(ExpandoObject expando)
{
var dict = (IDictionary<string, object>) expando;
var scriptObject = new ScriptObject();
foreach (var kv in dict)
{
var renamedKey = StandardMemberRenamer.Rename(kv.Key);
if (kv.Value is ExpandoObject expandoValue)
{
scriptObject.Add(renamedKey, BuildScriptObject(expandoValue));
}
else
{
scriptObject.Add(renamedKey, kv.Value);
}
}
return scriptObject;
}
}
它利用了一个事实,即 ExpandoObject
的复杂属性在从 JSON 反序列化时始终是 ExpandoObjects
。它以递归方式将复杂成员类型的 ScriptObjects
和所有其他属性的对象本身添加到 ``ScriptObject`。
请注意,我的解决方案使用了 Scriban 的默认成员重命名,其中 FirstName
变为 first_name
等等。
我想使用 ExpandoObject
或可以从 JSON 字符串生成的任何其他数据类型呈现 Scriban 模板:
var json = "....";
var dyn = JsonConvert.DeserializeObject<ExpandoObject>(json);
var template = Scriban.Template.Parse("Hello {{ data.foo }}!");
var result = template.Render(dyn);
Scriban 不适用于 ExpandoObject
s,因为它们被解析为 { key = '', value = '' }
对象的列表。在我的用例中,声明数据类型不是一个选项,因为 JSON 模式不是先验的。
将 ExpandoObject 转换为动态显示与直接使用
ExpandoObject
相同的行为。我尝试将 JSON 反序列化为
dynamic
,这会导致异常:
System.Reflection.TargetParameterCountException: "Parameter count mismatch."
我能否以某种方式转换数据或配置 Scriban 以呈现动态数据?
如果你有一个简单的对象,你可以尝试这样的事情。
var json = "{\"Phone\":\"555000000\",\"Name\":\"Maia\"}";
var scriptObject = new Scriban.Runtime.ScriptObject();
var data = JsonConvert.DeserializeObject<ExpandoObject>(json);
foreach (var prop in data)
{
scriptObject.Add(prop.Key, prop.Value);
}
var templateCtx = new Scriban.TemplateContext();
templateCtx.PushGlobal(scriptObject);
var template = Scriban.Template.Parse("Hello {{Name}}");
var result = template.Render(templateCtx); // result will be "Hello Maia"
根据之前的回答,这是复杂对象的解决方案:
public static class ScribanRenderer
{
public static string RenderJson(string json, string content)
{
var expando = JsonConvert.DeserializeObject<ExpandoObject>(json);
var sObject = BuildScriptObject(expando);
var templateCtx = new Scriban.TemplateContext();
templateCtx.PushGlobal(sObject);
var template = Scriban.Template.Parse(content);
var result = template.Render(templateCtx);
return result;
}
private static ScriptObject BuildScriptObject(ExpandoObject expando)
{
var dict = (IDictionary<string, object>) expando;
var scriptObject = new ScriptObject();
foreach (var kv in dict)
{
var renamedKey = StandardMemberRenamer.Rename(kv.Key);
if (kv.Value is ExpandoObject expandoValue)
{
scriptObject.Add(renamedKey, BuildScriptObject(expandoValue));
}
else
{
scriptObject.Add(renamedKey, kv.Value);
}
}
return scriptObject;
}
}
它利用了一个事实,即 ExpandoObject
的复杂属性在从 JSON 反序列化时始终是 ExpandoObjects
。它以递归方式将复杂成员类型的 ScriptObjects
和所有其他属性的对象本身添加到 ``ScriptObject`。
请注意,我的解决方案使用了 Scriban 的默认成员重命名,其中 FirstName
变为 first_name
等等。