【问题标题】:String to object in JSJS中的字符串到对象
【发布时间】:2010-11-08 08:31:08
【问题描述】:

我有一个字符串

string = "firstName:name1, lastName:last1"; 

现在我需要一个对象 obj 这样

obj = {firstName:name1, lastName:last1}

如何在 JS 中做到这一点?

【问题讨论】:

  • name1 和 last1 是在别处定义的字符串值或标识符吗?
  • 需要更多数据...如果键或值包含逗号或冒号,您该怎么办?
  • 如果你的字符串不是 JSON 格式,你可能需要使用 RegEp 来处理。

标签: javascript string object


【解决方案1】:

其实最好的解决方案是使用 JSON:

Documentation

JSON.parse(text[, reviver]);

示例:

1)

var myobj = JSON.parse('{ "hello":"world" }');
alert(myobj.hello); // 'world'

2)

var myobj = JSON.parse(JSON.stringify({
    hello: "world"
});
alert(myobj.hello); // 'world'

3) 将函数传递给 JSON

var obj = {
    hello: "World",
    sayHello: (function() {
        console.log("I say Hello!");
    }).toString()
};
var myobj = JSON.parse(JSON.stringify(obj));
myobj.sayHello = new Function("return ("+myobj.sayHello+")")();
myobj.sayHello();

【讨论】:

  • 不允许传入函数
  • 是的,但是严格来说,函数不应该在任何 JSON 对象中。因为你有 RPC 等,或者如果你愿意,你可以将函数的原型传递给 json,并且稍后再做eval
  • 恐怕根本不回答这个问题。如果每个人都改变问题以适应答案,那就太好了。你如何解析“firstName:name1,lastName:last1”?不是'{“你好”:“世界”}'。
  • 这没有回答问题,我不知道为什么它有这么多的赞成票。提问者(和我自己,我用谷歌搜索并最终来到这里)的数据不符合 JSON 标准,因此无法解析。
  • var a = "firstName:name1, lastName:last1"; JSON.parse('{' + a + '}') 抛出错误。
【解决方案2】:

您的字符串看起来像一个没有花括号的 JSON 字符串。

这应该可以工作:

obj = eval('({' + str + '})');

【讨论】:

  • 这是一个潜在的安全漏洞。我根本不推荐这种方法。
  • 这取决于数据的来源。有些人痴迷于安全。如果您控制数据,您可以更加务实地寻找解决方案。或者你的厨房和客厅之间有防盗门吗?
  • 那不行。它给你错误 'SyntaxError: Unexpected token :'。我已经在 Chrome 中检查过了。
  • 解决方案需要用括号括起来:obj = eval('({' + str + '})');
  • prc322:每个人都知道 eval() 不是很安全(这是轻描淡写的说法),但是使用 eval() 是上述问题的唯一正确答案,因为输入字符串不是有效的 JSON字符串 AND 输入字符串按名称引用其他变量。
【解决方案3】:

如果我理解正确:

var properties = string.split(', ');
var obj = {};
properties.forEach(function(property) {
    var tup = property.split(':');
    obj[tup[0]] = tup[1];
});

我假设属性名称在冒号的左边,而它的字符串值在右边。

请注意,Array.forEach 是 JavaScript 1.6 -- 您可能需要使用工具包来获得最大的兼容性。

【讨论】:

  • Hey Cdleary...我想知道您是否可以帮助我:stackoverflow.com/questions/9357320/… 抱歉,除了通过您的答案通过 cmets 之外,找不到其他方式与您联系
  • 完美职位。这个答案非常清楚地使用了 JavaScript 的基础知识,因此应该适用于每个浏览器
  • 我发现这种方法是一个好的开始,所以答案很有用。但是, xecute 有一个有效点,即它不容纳可能有逗号的字符串。如果您的代码需要处理带逗号的字符串,您可以沿着匹配引号的路径前进,但您仍然不会捕获引号被转义的情况。只需实现您需要的,然后停止。
  • 在提问者提出的解析文本的问题中,“what if”的问题是没有用的。我们可以接受给定的示例作为数据的代表,或者我们不能直接回答,因为总会有一个 "what if" 会破坏解析。
  • 发帖人询问如何解析一个非有效 JSON 的异常结构。 @cdleary 在这种情况下很好地回答了这个问题。 xecute:处理字符串中的逗号需要引用或转义机制,超出了本讨论的范围。
【解决方案4】:

这个简单的方法...

var string = "{firstName:'name1', lastName:'last1'}";
eval('var obj='+string);
alert(obj.firstName);

输出

name1

【讨论】:

  • 对此表示赞同,尽管:var string = "{firstName:'name1', lastName:'last1', f: function(){alert('你被黑了...')}( )}"; eval('var obj'+string) 这可能会让你被黑......但我认为它值得,因为它在某些情况下唯一有效。
  • 这是唯一可以直接解决问题的解决方案,尽管using eval is dangerous.
  • 目前,在浏览器中执行的任何 JS 代码都是危险的。坦率地说......这个答案是唯一可以有效解决“JS中的字符串到对象”问题的解决方案。 JSON.parse() 仅限于 JSON 的范围。记住 JSON 不是 JS 对象。谢谢! =D
【解决方案5】:

由于 JSON.parse() 方法需要将 Object 键括在引号中才能正常工作,因此我们首先必须将字符串转换为 JSON 格式的字符串,然后再调用 JSON.parse() 方法。

var obj = '{ firstName:"John", lastName:"Doe" }';

var jsonStr = obj.replace(/(\w+:)|(\w+ :)/g, function(matchedStr) {
  return '"' + matchedStr.substring(0, matchedStr.length - 1) + '":';
});

obj = JSON.parse(jsonStr); //converts to a regular object

console.log(obj.firstName); // expected output: John
console.log(obj.lastName); // expected output: Doe

即使字符串有一个复杂的对象(如下所示),它仍然可以正确转换。只需确保字符串本身包含在单引号内。

var strObj = '{ name:"John Doe", age:33, favorites:{ sports:["hoops", "baseball"], movies:["star wars", "taxi driver"]  }}';

var jsonStr = strObj.replace(/(\w+:)|(\w+ :)/g, function(s) {
  return '"' + s.substring(0, s.length-1) + '":';
});

var obj = JSON.parse(jsonStr);
console.log(obj.favorites.movies[0]); // expected output: star wars

【讨论】:

  • 这是不使用 eval() 的最接近的解决方案,并且几乎适用于 String 中的所有 JS 对象。但请注意,此解决方案不适用于时间戳作为值!即 {from:"2021-05-09T22:00:00.000Z"} 可能被转换为 {"from":"2021-05-09T"22":"00":00.000Z"}
【解决方案6】:

如果你有一个像foo: 1, bar: 2 这样的字符串,你可以将它转换为一个有效的obj:

str
  .split(',')
  .map(x => x.split(':').map(y => y.trim()))
  .reduce((a, x) => {
    a[x[0]] = x[1];
    return a;
  }, {});

感谢 #javascript 中的 niggler。

更新解释:

const obj = 'foo: 1, bar: 2'
  .split(',') // split into ['foo: 1', 'bar: 2']
  .map(keyVal => { // go over each keyVal value in that array
    return keyVal
      .split(':') // split into ['foo', '1'] and on the next loop ['bar', '2']
      .map(_ => _.trim()) // loop over each value in each array and make sure it doesn't have trailing whitespace, the _ is irrelavent because i'm too lazy to think of a good var name for this
  })
  .reduce((accumulator, currentValue) => { // reduce() takes a func and a beginning object, we're making a fresh object
    accumulator[currentValue[0]] = currentValue[1]
    // accumulator starts at the beginning obj, in our case {}, and "accumulates" values to it
    // since reduce() works like map() in the sense it iterates over an array, and it can be chained upon things like map(),
    // first time through it would say "okay accumulator, accumulate currentValue[0] (which is 'foo') = currentValue[1] (which is '1')
    // so first time reduce runs, it starts with empty object {} and assigns {foo: '1'} to it
    // second time through, it "accumulates" {bar: '2'} to it. so now we have {foo: '1', bar: '2'}
    return accumulator
  }, {}) // when there are no more things in the array to iterate over, it returns the accumulated stuff

console.log(obj)

令人困惑的 MDN 文档:

演示:http://jsbin.com/hiduhijevu/edit?js,console

功能:

const str2obj = str => {
  return str
    .split(',')
    .map(keyVal => {
      return keyVal
        .split(':')
        .map(_ => _.trim())
    })
    .reduce((accumulator, currentValue) => {
      accumulator[currentValue[0]] = currentValue[1]
      return accumulator
    }, {})
}

console.log(str2obj('foo: 1, bar: 2')) // see? works!

【讨论】:

  • 对于普通读者来说,这是一个完全无法理解的答案。你能解释一下每一行的作用吗?给定 OP 的输入,结果输出是什么?
  • 很公平。通常我没有时间详细说明东西,我只是放弃一些有用的东西(特别是如果我在路上遇到同样确切的 SO 问题),但我明白了。
  • 这绝对是最优雅的解决方案,并且与许多其他答案不同,它实际上回答了这个问题。并感谢您的解释!
【解决方案7】:

如果您使用的是 JQuery:

var obj = jQuery.parseJSON('{"path":"/img/filename.jpg"}');
console.log(obj.path); // will print /img/filename.jpg

记住:eval 是邪恶的! :D

【讨论】:

  • jQuery 使用evalglobalEval: /** code **/ window[ "eval" ].call( window, data ); /** more code **/
  • 问题所有者提供的字符串不是有效的 JSON 字符串。所以,这段代码没用……
  • 是的,如果您在“受控”环境(除了文件、网络或用户输入等外部数据之外的任何数据)上使用 eval ,它并不是邪恶的,在这种情况下,如果没有“过滤/验证”,它可能会很危险")。
【解决方案8】:

您需要使用 JSON.parse() 将 String 转换为 Object:

var obj = JSON.parse('{ "firstName":"name1", "lastName": "last1" }');

【讨论】:

    【解决方案9】:

    我用几行代码实现了一个非常可靠的解决方案。

    有一个像这样的 HTML 元素,我想在其中传递自定义选项:

    <div class="my-element"
        data-options="background-color: #dadada; custom-key: custom-value;">
    </div>
    

    一个函数解析自定义选项并返回一个对象以在某处使用它:

    function readCustomOptions($elem){
        var i, len, option, options, optionsObject = {};
    
        options = $elem.data('options');
        options = (options || '').replace(/\s/g,'').split(';');
        for (i = 0, len = options.length - 1; i < len; i++){
            option = options[i].split(':');
            optionsObject[option[0]] = option[1];
        }
        return optionsObject;
    }
    
    console.log(readCustomOptions($('.my-element')));
    

    【讨论】:

    • +1 用于使用data- 属性,而不是像某些框架/库那样创建伪自定义属性。
    【解决方案10】:
    string = "firstName:name1, lastName:last1";
    

    这将起作用:

    var fields = string.split(', '),
        fieldObject = {};
    
    if( typeof fields === 'object') ){
       fields.each(function(field) {
          var c = property.split(':');
          fieldObject[c[0]] = c[1];
       });
    }
    

    但是效率不高。当你有这样的事情时会发生什么:

    string = "firstName:name1, lastName:last1, profileUrl:http://localhost/site/profile/1";
    

    split() 将拆分“http”。所以我建议你使用像管道这样的特殊分隔符

     string = "firstName|name1, lastName|last1";
    
    
       var fields = string.split(', '),
            fieldObject = {};
    
        if( typeof fields === 'object') ){
           fields.each(function(field) {
              var c = property.split('|');
              fieldObject[c[0]] = c[1];
           });
        }
    

    【讨论】:

    • 只是一个想法-而不是第二个 split(':') 您可以使用 indexOf(":") 通过第一个冒号“手动”拆分字符串,并将字符串的部分视为该冒号键和冒号后的其余部分作为值。
    【解决方案11】:

    我正在使用JSON5,效果很好。

    好在它包含 no evalno new Function,使用非常安全。

    【讨论】:

      【解决方案12】:

      在你的情况下,简短而漂亮的代码

      Object.fromEntries(str.split(',').map(i => i.split(':')));
      

      【讨论】:

      • 这适用于平面对象,但不适用于具有子对象的更复杂情况。
      【解决方案13】:

      这是通用代码,无论您的输入有多长,但如果有:分隔符,则在相同的架构中:)

      var string = "firstName:name1, lastName:last1"; 
      var pass = string.replace(',',':');
      var arr = pass.split(':');
      var empty = {};
      arr.forEach(function(el,i){
        var b = i + 1, c = b/2, e = c.toString();
           if(e.indexOf('.') != -1 ) {
           empty[el] = arr[i+1];
        } 
      }); 
        console.log(empty)
      

      【讨论】:

        【解决方案14】:

        这是我处理一些边缘情况的方法,例如将空格和其他原始类型作为值

        const str = " c:234 , d:sdfg ,e: true, f:null, g: undefined, h:name "; 
        
        const strToObj = str
          .trim()
          .split(",")
          .reduce((acc, item) => {
            const [key, val = ""] = item.trim().split(":");
            let newVal = val.trim();
        
            if (newVal == "null") {
              newVal = null;
            } else if (newVal == "undefined") {
              newVal = void 0;
            } else if (!Number.isNaN(Number(newVal))) {
              newVal = Number(newVal);
            }else if (newVal == "true" || newVal == "false") {
              newVal = Boolean(newVal);
            }
            return { ...acc, [key.trim()]: newVal };
          }, {});
        

        【讨论】:

          【解决方案15】:

          你的情况

          var KeyVal = string.split(", ");
          var obj = {};
          var i;
          for (i in KeyVal) {
              KeyVal[i] = KeyVal[i].split(":");
              obj[eval(KeyVal[i][0])] = eval(KeyVal[i][1]);
          }
          

          【讨论】:

          • 应该不惜一切代价避免评估。
          【解决方案16】:
          var stringExample = "firstName:name1, lastName:last1 | firstName:name2, lastName:last2";    
          
          var initial_arr_objects = stringExample.split("|");
              var objects =[];
              initial_arr_objects.map((e) => {
                    var string = e;
                    var fields = string.split(','),fieldObject = {};
                  if( typeof fields === 'object') {
                     fields.forEach(function(field) {
                        var c = field.split(':');
                        fieldObject[c[0]] = c[1]; //use parseInt if integer wanted
                     });
                  }
                      console.log(fieldObject)
                      objects.push(fieldObject);
                  });
          

          “objects”数组将包含所有对象

          【讨论】:

            【解决方案17】:

            我知道这是一篇旧帖子,但没有看到问题的正确答案。

            var jsonStrig = '{';
                  var items = string.split(',');
                  for (var i = 0; i < items.length; i++) {
                      var current = items[i].split(':');
                      jsonStrig += '"' + current[0] + '":"' + current[1] + '",';
                  }
                  jsonStrig = jsonStrig.substr(0, jsonStrig.length - 1);
                  jsonStrig += '}';
            var obj = JSON.parse(jsonStrig);
            console.log(obj.firstName, obj.lastName);
            

            现在您可以使用obj.firstNameobj.lastName 来获取值,就像您通常可以使用对象一样。

            【讨论】:

              猜你喜欢
              • 2011-01-16
              • 1970-01-01
              • 2010-10-24
              • 1970-01-01
              • 2022-06-10
              • 1970-01-01
              • 1970-01-01
              • 2012-10-11
              相关资源
              最近更新 更多