1

我想使用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 模式不是先验已知的。

  • 将 ExpandoObject 转换为动态显示与ExpandoObject直接使用相同的行为。

  • 我尝试反序列化dynamic导致异常的 JSON:

System.Reflection.TargetParameterCountException:“参数计数不匹配。”

我可以以某种方式转换数据或配置 Scriban 以呈现动态数据吗?

4

2 回答 2

4

基于前面的答案,这是一个复杂对象的解决方案:

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;
    }
}

它利用了一个事实,即当它从 JSON 反序列化时,它的复杂属性ExpandoObject总是存在的。ExpandoObjects它递归地将ScriptObjects复杂的成员类型和对象本身的所有其他属性添加到“ScriptObject”。

请不要说我的解决方案使用 Scriban 的默认成员重命名,在哪里FirstName变成first_name等等。

于 2020-04-18T08:34:19.923 回答
2

如果你有一个简单的对象,你可以尝试这样的事情。

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"
于 2020-03-30T17:53:17.810 回答