Luciano Meireles
Luciano Meireles

Reputation: 13

String to Object with reference

How can I convert a string to an object when there is a reference inside the string?

String:

{ "field": "OrderNumber", "operator": "eq", "value" : e.data.OrderNumber }

I already tried with JSON.parse and eval but I'm still getting an error on "e.data.OrderNumber"

Upvotes: 1

Views: 218

Answers (5)

Luciano Meireles
Luciano Meireles

Reputation: 13

It's worked with this:

    private static rev(key: any, value: any): any {
        if (key === "value") {
            let [props, val] = [value.split(".").slice(1), void 0];
            for (let prop of props) {
                val = val === undefined ? this[prop] : val[prop];
            }
            return val;
        }
        return value;
    }

And i use JSON.parse(relationString, this.rev.bind(e)) to call the method

Upvotes: 0

guest271314
guest271314

Reputation: 1

Set "value" to empty string. Call JSON.parse() with str as parameter. Set .value of resulting object.

var str = `{"field":"OrderNumber","operator":"eq","value":""}`;

var obj = JSON.parse(str);

obj.value = e.data.OrderNumber;

An alternative approach would be to utilize JSON.parse() reviver function, with this set to e using Function.prototype.bind(). If key is equal to "value" within the function create a variable val where the value is initially set to undefined. Use .split() to create an array of the property representations within the key "value". .slice() the indexes following 0 from resulting array. Use for..of loop to get the value of obj[arrayIndex] through obj[arrayIndex][propN] where propN is the nth index of array; assign the value to the variable val. Return the variable val following loop, else return value parameter.

var e = {
  data: {
    OrderNumber: 1
  }
};

var str = '{"field":"OrderNumber","operator":"eq","value":e.data.OrderNumber}';

str = str.replace(/((\w+.[\w.]+)(?=(\s+|)\}))/g, "\"$1\"");

var rev = function(key, value) {
  if (key === "value") {
    let [props, val] = [value.split(".").slice(1), void 0];
    for (let prop of props) {
      val = val === undefined ? this[prop] : val[prop];
    }
   return val;
  }
  return value;
};

var obj = JSON.parse(str, rev.bind(e));

console.log(obj);

You can also retrieve and set the value without having the property name using String.prototype.replace() with RegExp /((\w+.[\w.]+)(?=(\s+|)\}))/g to match word character followed by . followed by one of more word characters and . characters; String.prototype.match() to match word characters and create an array from the matches; Array.prototype.reduce() to iterate each depth of object properties for the .length of the array, return the last value at depth of array .length corresponding to object properties within original string.

const e = {
  data: {
    OrderNumber: 1
  }
};

let str = '{ "field": "OrderNumber", "operator": "eq", "value" : e.data.OrderNumber }';

str = str.replace(/((\w+.[\w.]+)(?=(\s+|)\}))/g, function(match) {
  let [,...props] = match.match(/[^.]+/g);
  return props.reduce(function(obj, prop) {
    return obj[prop]
  }, e); 
});

let obj = JSON.parse(str);

console.log(obj);

With resulting array from calls to .match(), .shift(), .split() on original string you can get the property values from e with destructuring assignment; use .replace() to set replacement string with corresponding value from e; then call JSON.parse() with resulting string as value to create a javascript object.

const e = {
  data: {
    OrderNumber: 1
  }
};

let str = '{ "field": "OrderNumber", "operator": "eq", "value" : e.data.OrderNumber }';

let re = /((\w+.[\w.]+)(?=(\s+|)\}))/g;

let obj = JSON.parse(str.replace(re
          , (() => ([,...props] = str.match(re).shift().split(".")
            , {[props[0]]:{[props[1]]:prop}} = e, prop)
            )()
          ));

console.log(obj);

Upvotes: 2

zfrisch
zfrisch

Reputation: 8660

https://jsfiddle.net/hd3v29ra/2/

You would simply need to adjust the order number to reside within quotations when you insert it into the string to be converted into an object:

example 1 using concatenated strings

var obj = JSON.parse('{"field": "OrderNumber","operator": "eq","value":"' + e.data.orderNumber + '"}');

example 2 using ES6 Template Literals

var obj = JSON.parse(`{"field": "OrderNumber", "operator":"eq","value":"${e.data.orderNumber}"}`);

Upvotes: 1

epascarello
epascarello

Reputation: 207501

Only real option you have to to use eval or new Function since what you have is not valid JSON due to the object property reference. There are security concerns with new Function and eval, so that is why this solution is not the best idea.

var str = '{ "field": "OrderNumber", "operator": "eq", "value" : e.data.OrderNumber }';
var e = { data : { OrderNumber : 123456 } };
var x = new Function("return " + str)();
console.log(x.value);

BUT if I were you, I would see if there is a better way to do what you need instead of using a bandaid to fix the problem. What I would do is have an object and add the property or extend it.

var e = { data : { OrderNumber : 123456 } };
var obj = { "field": "OrderNumber", "operator": "eq" };
obj.value = e.data.OrderNumber;

or

var e = { data : { OrderNumber : 123456 } };
var obj = { "field": "OrderNumber", "operator": "eq" };
var result = {};
Object.assign(result, obj, {value : e.data.OrderNumber} );

Upvotes: 2

Oriol
Oriol

Reputation: 288100

There is the unsafe and evil eval:

var e = {data: {OrderNumber: 123}};
var str = '{ "field": "OrderNumber", "operator": "eq", "value" : e.data.OrderNumber }';
console.log(eval('(' + str + ')'));

Do not use this with untrusted strings, it may run arbitrary code.

Upvotes: 0

Related Questions