0

Here is some information about the technologies used in my application:

  • Microsoft Visual Studio Enterprise 2022 (64-bit) - Current
  • Stubble.Core version 1.10.8 ( library used to apply Mustache "logic-less templates" to json input data )
  • .NET 6.0

Here is the snippet of the C# code that invokes Stubble API:

var objData = (JObject)JsonConvert.DeserializeObject(jsonData);
var stubble = new StubbleBuilder().Build();
string body = stubble.Render(template.TemplateBody, objData);

In our C# code, we have a string-based variable called template.TemplateBody which contains the following Mustache-based Stubble template:

{{#should_render}} If the relevant value in the custom_parameters_json
is true then this should be shown! {{/should_render}}

List seems to work as expected {{#my_list}} item: {{.}} {{/my_list}}

{{#truthy_value}} Truthy values should also work {{/truthy_value}}

{{#some_string}} String should be rendered if it is not null {{.}}
{{/some_string}}

Here is a generalized format of the JSON-based input test data:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
        "should_render": { "type": "boolean" },
       "my_list": { "type": "array" },
        "truthy_value": { "type": "integer" },
        "some_string": { "type": "string" }
    } 
}

In our C# code, we also have a string-based variable called jsonData:

{
  "should_render":true,
  "my_list": ["a","b","c"],
  "truthy_value":1,
  "some_string":"My String"
}

Ultimately, jsonData will be deserialized into a C# object, stored in a variable called objData:

{   
  "should_render": true,
  "my_list": ["a", "b", "c"],
  "truthy_value": 1,
  "some_string": "My String" 
}

After applying the Stubble template to the JSON object data, it renders the following output:

\nList seems to work as expected\nitem: a\nitem: b\nitem: c\n\n\n

In the input JSON test data, should_render is set to true:

"should_render": true

Therefore, I am asking:

  1. Why did the Stubble API fail to render the statement "If the relevant value in the custom_parameters_json is true then this should be shown!" when should_render was set to true?
{{#should_render}} If the relevant value in the custom_parameters_json is true then this should be shown! {{/should_render}}
  1. Why did the Stubble API fail to render the statement "Truthy values should also work" when truthy_value was set to 1?
{{#truthy_value}}  Truthy values should also work {{/truthy_value}}
  1. Why did the Stubble API fail to render the statement "String should be rendered if it is not null {{.}}" when some_string was populated?
{{#some_string}}  String should be rendered if it is not null {{.}} {{/some_string}}

Could someone please explain what modifications might be needed to get the following rendered output?

If the relevant value in the custom_parameters_json is true then this should be shown!

List seems to work as expected item: a item: b item: c

Truthy values should also work

String should be rendered if it is not null My String

1 Answer 1

0

All:

Mistral-Medium gave me the following answer:

The issue you're experiencing is related to how Stubble handles the data context when rendering templates. The problem stems from the fact that you're using JObject from Newtonsoft.Json as your data model, which doesn't play perfectly with Stubble's default behavior.

Here's what's happening and how to fix it:

Root Causes:

  1. JObject vs Dictionary: Stubble works best with Dictionary<string, object> or POCOs (Plain Old CLR Objects). When you deserialize to JObject, Stubble might not properly traverse the object graph.

  2. Truthy values: Stubble has specific rules about what it considers "truthy" for boolean checks. Numbers (like your truthy_value: 1) might not be treated as truthy by default.

  3. String rendering: The . in {{.}} refers to the current context, which might not work as expected with JObject.

Solutions:

  1. Convert JObject to Dictionary:

csharp

var objData = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonData);
  1. Or create a proper POCO:

csharp

public class TemplateData
{
    public bool ShouldRender { get; set; }
    public List<string> MyList { get; set; }
    public int TruthyValue { get; set; }
    public string SomeString { get; set; }
}

// Then deserialize:
var objData = JsonConvert.DeserializeObject<TemplateData>(jsonData);
  1. For your specific template, here's how to modify your code:

csharp

// Option 1: Using Dictionary
var objData = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonData);
var stubble = new StubbleBuilder().Build();
string body = stubble.Render(template.TemplateBody, objData);

// Option 2: Using POCO (recommended)
var objData = JsonConvert.DeserializeObject<TemplateData>(jsonData);
var stubble = new StubbleBuilder().Build();
string body = stubble.Render(template.TemplateBody, objData);

Expected Output:

With either solution, you should now get:

livecodeserver

If the relevant value in the custom_parameters_json is true then this should be shown!
List seems to work as expected
item: a
item: b
item: c

Truthy values should also work
String should be rendered if it is not null My String

Additional Notes:

  1. For the truthy_value to work, you might need to ensure Stubble treats non-zero numbers as truthy. This is usually the default behavior, but if it's not working, you might need to configure Stubble differently.

  2. The {{.}} syntax works when you're in a section (like #my_list) to refer to the current item. For your some_string case, you should just use {{some_string}} instead of the section syntax unless you specifically need the section behavior.

  3. If you must use JObject, you could try:

csharp

var objData = JObject.Parse(jsonData);
var stubble = new StubbleBuilder()
    .Configure(settings => settings.SetValueDelegate = (obj, propertyName) =>
    {
        if (obj is JObject jObj && jObj.TryGetValue(propertyName, out var value))
        {
            return value.ToString();
        }
        return null;
    })
    .Build();
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.