【问题标题】:Render scriban template from json data从 json 数据渲染 scriban 模板
【发布时间】:2020-04-18 16:34:19
【问题描述】:

我想使用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 相同的行为。

  • 我尝试将 JSON 反序列化为 dynamic,这会导致异常:

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

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

【问题讨论】:

    标签: c# json scriban


    【解决方案1】:

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

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

    【讨论】:

      【解决方案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"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-05
        • 1970-01-01
        • 2016-08-23
        • 2016-11-13
        • 2018-10-08
        • 1970-01-01
        • 2016-02-21
        • 2011-12-27
        相关资源
        最近更新 更多