从JSON数据渲染scriban模板

nxowjjhe  于 2023-10-21  发布在  其他
关注(0)|答案(3)|浏览(119)

我想渲染一个Scriban模板,它包含ExpandoObject或任何其他可以从JSON字符串生成的数据类型:

var json = "....";                
var dyn = JsonConvert.DeserializeObject<ExpandoObject>(json);                    
var template = Scriban.Template.Parse("Hello {{ data.foo }}!");                    
var result = template.Render(dyn);

Scriban不适用于ExpandoObject,因为它们被解析为{ key = '', value = '' }对象的列表。在我的用例中,为数据声明一个类型不是一个选项,因为JSON模式不是先验已知的。

  • 将ExpandoObject转换为dynamic与直接使用ExpandoObject的行为相同。
  • 我尝试将JSON转换为dynamic,这导致了一个异常:

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

我可以转换数据或配置Scriban来呈现动态数据吗?

ecbunoof

ecbunoof1#

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

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时始终是ExpandoObjects的事实。它递归地将复杂成员类型的ScriptObjects和所有其他属性的对象本身添加到``ScriptObject。 请注意,我的解决方案使用Scriban的默认成员重命名,其中FirstName变为first_name`,依此类推。

uurity8g

uurity8g2#

不确定以前的版本是否支持这样做,但看起来这更有效,Scriban examplegithub)可以做到这一点。

var json = "{\"name\":{\"first\":\"Maia\"}}";
var template = Template.Parse("Hello {{model.name.first}}");        
var result = template.Render(new { model = JsonConvert.DeserializeObject<ExpandoObject>(json) });

Console.WriteLine(result);

// Output: Hello Maia
gev0vcfq

gev0vcfq3#

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

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"

相关问题