Reputation: 69
I'm trying to generate a JSON file with mustache with the following template:
{
"name": "{{customer_info.first_name}}",
"email": "{{contact_info.email}}",
"campaign": {
"campaignId": "{{contact_info.campaign.campaignId}}"
},
"tags": [
{{#contact_info.tags}}
{
"tagId": "{{tagId}}"
},
{{/contact_info.tags}}
]
}
As an output example I get:
{
"name": "Antonio",
"email": "[email protected]",
"campaign": {
"campaignId": "pfft"
},
"tags": [
{
"tagId": "6prrtAP"
},
{
"tagId": "64rrrE9"
},
]
}
Which unluckily is a BAD FORMATTED JSON, because there is a not wanted "," after the last element in the array.
Can any of you help me in solving this issue and remove the comma ?
Thanks a lot
Upvotes: 6
Views: 16492
Reputation: 1000
This looks like a good answer:
contact_info['tags'][ contact_info['tags'].length - 1 ].last = true;
and the template would be
{{#contact_info.tags}}
{
"tagId": "{{tagId}}"
} {{^last}}, {{/last}}
{{/contact_info.tags}}
Source: https://stackoverflow.com/a/7591866
Upvotes: 0
Reputation: 19236
Don't generate JSON from textual templates. You'll constantly face problems like this. Superfluous commas, meta characters in strings (what if customer_info.first_name
contains double quotes), failing to properly nest structures etc.
Generate your data as native structures in your programming language, and encode it as JSON using library provided by your programming language.
However, if you absolutely need, try to generate as much JSON data as possible (ideally, self-contained JSON fragment) outside template, and interpolate that inside template. For example:
let contact_info = {"tags": [ "6prrtAP", "64rrrE9" ]}
let tags = contact_info.tags.map((tag) => ({"tagId": tag})); // [{tagId: "6prrtAP"}, {tagId: "64rrrE9"}]
let tagsJSON = JSON.stringify(tags); // "[{\"tagId\":\"6prrtAP\"},{\"tagId\":\"64rrrE9\"}]"
Then, pass tagsJSON
to your template:
{
"name": "{{customer_info.first_name}}",
"email": "{{contact_info.email}}",
"campaign": {
"campaignId": "{{contact_info.campaign.campaignId}}"
},
"tags": {{tagsJSON}}
}
That way, tagsJSON
always contains valid JSON-encoded data, so it might be safely interpolated as a value in JSON dictionary/object. Even if tag list is empty, even if tag IDs suddenly start to contain characters that need escaping etc. All corner cases are already handled for you.
Upvotes: 2
Reputation: 306
Try using SelectTransform npm package. It has Mustache like syntax without all the side-effects that Mustache creates and the package size is also not as heavy as Handlebars.js
import ST from "stjs";
const data = {
name: 'Jakub',
friends: [
{
name: 'Michal'
}
]
};
const template = {
newName: '{{ name }}',
friends: {
'{{ #each friends }}': {
subName: '{{ name }}'
}
}
};
console.log(ST.select(data).transformWith(template).root());
// Result:
/**
* {
* "newName": "Jakub",
* "friends": [
* {
* "subName": "Michal"
* }
* ]
* }
*/
Upvotes: 2
Reputation: 913
I've been experiencing some similar problem and I found out that Handlebars is a lot similar to mustache and way more powerful.
You could check that out and try using this template to solve your problem, without adding anything to your current model.
{
"name": "{{customer_info.first_name}}",
"email": "{{contact_info.email}}",
"campaign": {
"campaignId": "{{contact_info.campaign.campaignId}}"
},
"tags": [
{{#each contact_info.tags}}
{
"tagId": "{{tagId}}"
}{{#unless @last}},{{/unless}}
{{/each}}
]
}
Upvotes: 1
Reputation: 6252
I would do this:
var md = {};
var tagsCount = 2;
var currTagIndex = 0;
md['show_comma'] = function(){
currTagIndex++;
return currTagIndex <= tagsCount;
}
Then in Mustache template:
{{#show_comma}}
,
{{/show_comma}}
Upvotes: 4