【问题标题】:String to Object with reference带引用的字符串到对象
【发布时间】:2016-12-16 20:30:53
【问题描述】:

当字符串中有引用时,如何将字符串转换为对象?

字符串:

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

我已经尝试过使用 JSON.parse 和 eval,但在“e.data.OrderNumber”上仍然出现错误

【问题讨论】:

  • obj.value=e.data.OrderNumber
  • 那不是一个有效的 JSON。 e.data.OrderNumber 应该被视为这样的字符串:"e.data.OrderNumber"

标签: javascript


【解决方案1】:

"value" 设置为空字符串。使用str 作为参数调用JSON.parse()。设置结果对象的.value

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

var obj = JSON.parse(str);

obj.value = e.data.OrderNumber;

另一种方法是使用JSON.parse()reviver 函数,将this 设置为e,使用Function.prototype.bind()。如果key 等于函数内的"value",则创建一个变量val,其中值最初设置为undefined。使用.split()key "value" 中创建一个属性表示数组。 .slice() 来自结果数组的 0 之后的索引。使用for..of循环通过obj[arrayIndex][propN]获取obj[arrayIndex]的值,其中propN是数组的第n个索引;将值赋给变量val。循环后返回变量val,否则返回value参数。

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

您也可以在没有属性名称的情况下检索和设置值,使用 String.prototype.replace()RegExp /((\w+.[\w.]+)(?=(\s+|)\}))/g 来匹配单词字符后跟 . 后跟多个单词字符之一和 . 字符; String.prototype.match() 匹配单词字符并从匹配中创建一个数组; Array.prototype.reduce() 为数组的.length 迭代每个对象属性的深度,返回数组.length 与原始字符串中对象属性对应的深度处的最后一个值。

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

通过对原始字符串上的.match().shift().split() 的调用产生的数组,您可以通过解构赋值从e 获取属性值;使用.replace() 设置替换字符串与e 中的对应值;然后调用 JSON.parse() 并将结果字符串作为值来创建一个 javascript 对象。

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

【讨论】:

  • 如果事先知道字符串,则可以使用对象初始化器代替字符串。
  • @Oriol 是的,虽然问题的实际文本是 "String to Object with refence"
【解决方案2】:

您必须使用 eval 或 new Function 的唯一真正选项,因为由于对象属性引用,您所拥有的不是有效的 JSON。 new Function 和 eval 存在安全问题,这就是为什么这个解决方案不是最好的主意。

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

但如果我是你,我会看看是否有更好的方法来做你需要的事情,而不是使用创可贴来解决问题。我要做的是拥有一个对象并添加属性或扩展它。

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

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

【讨论】:

  • 为什么是new Function 而不仅仅是eval
  • @Evert 个人喜好?
  • 但数据值不会是 OrderNumber,我将使用此字符串作为过滤器上下文:filter: JSON.parse(relationString)
  • 属性无关紧要。您可以将其设置为任何值。
  • 但要使模板正常工作,我必须使用代码中的直接字符串,在我的情况下它来自数据库
【解决方案3】:

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

当您将订单号插入要转换为对象的字符串时,您只需将订单号调整为驻留在引号内:

使用连接字符串的示例 1

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

使用 ES6 模板文字的示例 2

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

【讨论】:

  • 但数据值不会是 OrderNumber,我将使用此字符串作为过滤器上下文:filter: JSON.parse(relationString)
【解决方案4】:

有不安全和邪恶eval

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

不要将它与不受信任的字符串一起使用,它可能会运行任意代码。

【讨论】:

  • 但数据值不会是 OrderNumber,我将使用此字符串作为过滤器上下文:filter: JSON.parse(relationString)
【解决方案5】:

它是这样工作的:

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

我使用 JSON.parse(relationString, this.rev.bind(e)) 来调用方法

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-07-03
  • 2010-11-12
  • 2013-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 1970-01-01
相关资源
最近更新 更多