从 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 不适用于 ExpandoObjects,因为它们被解析为 { key = '', value = '' } 对象的列表。在我的用例中,声明数据类型不是一个选项,因为 JSON 模式不是先验的。

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 等等。