user320550
user320550

Reputation: 1185

json template engine in node.js

I have a json template like the following:

[
  {
    "type":"foo",
    "config":"{config}"
  },
  {
    "type":"bar",
    "arrConfig":"{arrConfig}"
  }
]

While i have a backing model like:

{
  "config": {
    "test1": "value1",
    "test2": "value2"
  },
  "arrConfig": [
    "test3": {
      "key1": "val1"
    },
    "test4": {
      "key1": "val1"
    }
  ]
}

I'm wondering if there are any node modules out there which will automatically take these two and transform the placeholders in the template. So the output would look like:

[
  {
    "type":"foo",
    "config":{
      "test1": "value1",
      "test2": "value2"
    }
  },
  {
    "type":"bar",
    "arrConfig": [
      "test3": {
        "key1": "val1"
      },
      "test4": {
        "key1": "val1"
      }
    ]
  }
]

Upvotes: 3

Views: 7119

Answers (3)

Kevindra
Kevindra

Reputation: 1762

You can use Mustache, like so:

var template = [
  {
    type: "foo",
    config: "{{config}}"
  }
];

var data = {
  config: "hello"
};

const Mustache = require("mustache");

function render(template, data) {
  return Mustache.render(JSON.stringify(template), data);
}

var output = render(template, data);
console.log(output);  // [{"type":"foo","config":"hello"}]

Upvotes: 1

Tiago Engel
Tiago Engel

Reputation: 3661

JSON.stringify accepts a replacer param that you could use to do it.

This should work:

var template = [
  {
    "type":"foo",
    "config":"{config}"
  },
  {
    "type":"bar",
    "arrConfig":"{arrConfig}"
  }
];


var data = {
  "config": {
    "test1": "value1",
    "test2": "value2"
  },
  "arrConfig": {
    "test3": {
      "key1": "val1"
    },
    "test4": {
      "key1": "val1"
    }
  }
};

var replacer = function (key, val) {
   if (typeof val === 'string' && val.match(/^{(.+)}$/)) {
     return data[val.replace(/[{|}]/g, '')]
   }
   return val;
 }

 console.log(JSON.stringify(template, replacer));

And if you want to transform it back to an object you can use JSON.parse

Upvotes: 6

qxz
qxz

Reputation: 3864

Here is a function to traverse an object hierarchy and replace template strings, as specified:

// modifies the object passed, and returns the same object
function applyTemplate(template, backing) {
  for (var i in template) {
    var m = /^{(.+)}$/.exec(template[i]);
    if (m && backing[m[1]]) {
      // replace with a deep clone of the value from the backing model
      template[i] = JSON.parse(JSON.stringify(backing[m[1]]));
    } else if (template[i] && "object" == typeof template[i]) {
      // traverse down recursively
      applyTemplate(template[i], backing);
    }
  }
  return template;
}

var template = [
  {
    "type":"foo",
    "config":"{config}"
  },
  {
    "type":"bar",
    "arrConfig":"{arrConfig}"
  }
];

var backing = {
  "config": {
    "test1": "value1",
    "test2": "value2"
  },
  "arrConfig": {
    "test3": {
      "key1": "val1"
    },
    "test4": {
      "key1": "val1"
    }
  }
};

applyTemplate(template, backing);
console.log(JSON.stringify(template, null, 2));

Plus a proof-of-concept using raw JSON text replacement (not robust, don't actually use this; but works for the vast majority of scenarios):

function applyTemplateStr(template, backing) {
  template = JSON.stringify(template);
  for (var key in backing) {
    template = template.split('"{'+key+'}"').join(JSON.stringify(backing[key]));
  }
  return JSON.parse(template);
}

Upvotes: 4

Related Questions