3

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"
      }
    ]
  }
]
2
  • I mean a quick & dirty solution would to just do text replacement on the JSON. You could write your own function to recursively traverse an object hierarchy and replace matching text values. Commented Aug 6, 2016 at 1:04
  • I think it's a bit more complex that since the placeholder values might be an object, array, string, number etc... So accordingly i will have to replace it Commented Aug 6, 2016 at 4:28

3 Answers 3

6

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

Sign up to request clarification or add additional context in comments.

Comments

4

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);
}

Comments

1

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"}]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.