1

Let's say I have:

 var json = '{"greetings": "`${greetings}`"}';
 var obj = JSON.parse(json);
 var template = obj.greetings; //`${greetings}`

 var greetings = 'hello';

how to evaluate template to get hello ?

user310291
  • 36,946
  • 82
  • 271
  • 487
  • 1
    You are basically trying to add template literal to JSON format, which isnt a valid syntax. – Thanveer Shah Jul 11 '20 at 23:08
  • You can try `eval`: `eval(template)`. – kaveh Jul 11 '20 at 23:17
  • @kaveh But isn't `eval` a really bad practice. – Thanveer Shah Jul 11 '20 at 23:19
  • 1
    @ThanveerShah it depends. If you trust the source of the json object, then it's fine. But if you don't have control over its content, then yes, it can break your code. You can validate the template with a regex though! – kaveh Jul 11 '20 at 23:21
  • 1
    Related and worth reading based on question https://stackoverflow.com/questions/37243791/are-es6-template-literals-safer-than-eval – charlietfl Jul 11 '20 at 23:59
  • Is there any way you can provide more info on where the JSON is coming from and when `greetings` is being defined? I see the JavaScript tag, is this react you are trying to do? – Bens Steves Jul 12 '20 at 01:01
  • @BensSteves JSON can come from a file or an api. No I don't want to use any framework like React since that's all such need: template string ;) – user310291 Jul 12 '20 at 04:18
  • @user310291 Based on that reading and other attempts I've made to use a *template tag function* I've come to conclusion that using eval() is the only way to compile it from json – charlietfl Jul 12 '20 at 06:09

1 Answers1

0

Since JSON.parse() returns obj.greetings as string, you can use eval() to run the string as js. So just:

var json = '{"greetings": "`${greetings}`"}';
var obj = JSON.parse(json);
var template = eval(obj.greetings); //`${greetings}`

var greetings = 'hello';
console.log(greetings)// hello

But eval() should always be used with caution as string maybe entered through user input.

Edit:

The above code with eval returns undefined. This is because JavaScript Hoisting doesn't work for initialized variable.

So we surely need to move the initialisation var greetings = 'hello'; at the top. Solution without eval():

Apply template string to the whole string.

var greetings = 'hello';

var json = `{"greetings": "${greetings}"}`;
var obj = JSON.parse(json);
var template = obj.greetings; //`${greetings}`

console.log(template); //hello
Neetigya Chahar
  • 683
  • 5
  • 14
  • In your code, value of `template` won't be `${greetings}` anymore and cannot be used later in the code. `eval` must be called on `template. See my comment on the question. – kaveh Jul 11 '20 at 23:20
  • 1
    `var greetings` will not get hoisted with a value, try running this by putting it in a stack snippet ( click `<>`) in answer editor – charlietfl Jul 11 '20 at 23:20
  • The back ticks for whole string are a good idea but worth noting wouldn't be practical if json is from remote source. Template literals are parsed at compile time so the string will have "hello" in it before JSON.parse() even runs. `template` does not return `${greetings}` it already has value `"hello"` – charlietfl Jul 12 '20 at 00:07
  • @charlietfl yeah, in this simple case it works, but in cases when `greetings` is changed again after `var json` is initialised and before `JSON.parse()`, it will still return the old value. Even passing object reference so as to update later won't work since its ultimately looses the reference after parsing. – Neetigya Chahar Jul 12 '20 at 00:33