StubbleOrg / Stubble

Trimmed down {{mustache}} templates in .NET
Other
405 stars 58 forks source link

Stubble Compilation doesn't render correctly from Dictionary<string, object> #59

Closed kislovs closed 5 years ago

kislovs commented 5 years ago

I have the following template:

{{#infoRows}}
Caption: {{caption}} <br>
Party: { Name: {{party.name}} } <br> <br>
{{/infoRows}} 

and have following data in json

{
  "infoRows": [
    {
      "caption": "Caption #1",
      "party": {
        "name": "Party Name #1"
      }
    },
    {
      "caption": "Caption #2",
      "party": {
        "name": "Party Name #2"
      }
    }
  ]
}

Which look this way as at runtime: image

When I use usual new StubbleBuilder().Build().Render(Template, Context), I get this: image

When I use compilation

var renderer = new StubbleCompilationBuilder()
    .Build()
    .Compile<Dictionary<string, object>>(Template);
renderer(Context)

I get this: image

Why does it work this way?

Romanx commented 5 years ago

Hi there,

Unfortunately the reason for this is due to the fact you're passing a Dictionary<string, object> which means the compilation renderer has no idea of the types you're passing and so can't be sure what it needs to render.

If you convert your JSON into full classes then it should work correctly. This is unfortunately one of the limitations of the compilation renderer since the work is done upfront to make the rendering very fast

kislovs commented 5 years ago

Unfortunately, I can't create full classes, because I have no idea what JSON I get, because user defines template, save it and later use that to render that template with requested data.

I have debugged it a little bit and found that method which should create compiled context mismatch nesting level (it should be { caption, src.Item["Param_0"].Item["caption"] }, but it matches { caption, src.Item["caption"] }.
(if src.Item["Param_0"] is for element of array/list)

Btw, I have seen methods for dynamic, maybe I can use that for my purposes?

Romanx commented 5 years ago

Dynamic will have the same problem if you're looking to compile. I'd recommend using the standard renderer if you're not sure about the shape of your input.

Also if you're using JSON I'd suggest looking at Stubble.Extensions.JsonNet which may make it a little easier for you since you can just parse into JObject. Only if you're using JsonNet though

kislovs commented 5 years ago

Okay, I will use usual async rendering. It will speed up template rendering and reduce memory usages by 4 times in comparison with library which I used before. So thank you for the library and thank you for fast reply :)

Romanx commented 5 years ago

No worries, please let us know if you have any issues!