JS中的对象字符串


190

我有一个字符串

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

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

obj = {firstName:name1, lastName:last1}

如何在JS中做到这一点?


1
name1和last1字符串值或标识符是否在其他地方定义?
cdleary

1
需要更多数据...如果键或值包含逗号或冒号,您该怎么办?
布拉德(Brad)

如果您的字符串不是格式化为JSON,则可能必须使用RegEp进行处理。
bitfishxyz

Answers:


165

实际上,最好的解决方案是使用JSON:

文献资料

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

不会允许传递函数
K2xL 2014年

2
的确如此,但是严格来讲,函数不应位于任何JSON对象中。为此,您具有RPC等,或者如果需要,可以将函数的原型传递给j​​son,然后再做eval
Matej 2014年

36
恐怕根本不回答这个问题。如果每个人都更改问题以适合答案,那就太好了。您如何解析“ firstName:name1,lastName:last1”?不是'{“ hello”:“ world”}'。
Noel Abrahams 2014年

33
这不能回答问题,我不知道为什么会有这么多的投票。发问者(和我本人,我在Google上搜索并结束于此处)的数据不符合JSON标准,因此无法进行解析。
亚伦·格林瓦尔德

1
var a =“ firstName:name1,lastName:last1”; JSON.parse('{'+ a +'}')引发错误。
亚伦·格林沃尔德

73

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

然后,这应该起作用:

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

22
这是一个潜在的安全漏洞。我根本不会推荐这种方法。
布列塔尼

64
这取决于数据来自何处。有些人痴迷于安全性。如果控制数据,则在寻找解决方案时会更加务实。还是在厨房和客厅之间设有防盗门?
菲利普·莱伯特

13
那不行 它给您错误'SyntaxError:Unexpected token:'。我已经在Chrome浏览器中对其进行了检查。
Nyambaa 2011年

12
解决方案需要用括号括起来:obj = eval('({' + str + '})');
Christian

12
prc322:每个人都知道eval()并不是很安全(这是一种轻描淡写的说法),但是使用eval()是上述问题的唯一正确答案,因为输入字符串不是有效的JSON字符串,并且输入字符串引用了其他变量按名字。
菲利普·莱巴特

50

如果我正确理解:

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

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

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


嘿Cdleary ...我想知道您是否能帮助我:stackoverflow.com/questions/9357320/…对不起,除了通过对您的回答的评论外,找不到其他与您联系的方式
Jason

1
县长职位。这个答案使用JavaScript的基础知识非常清晰,因此应该在每个浏览器的工作原理
米歇尔

我发现这种方法是一个好的开始,因此答案很有用。但是,xecute有一个有效的点,即它不容纳可能带有逗号的字符串。如果您的代码需要使用逗号来处理字符串,则可以选择匹配引号的路径,但是您仍然不会遇到引号被转义的情况。只需执行您需要的内容,然后停止即可。
帕特里克·格雷厄姆

1
在解析询问者提出的文本的问题中,“如果”的问题是无用的。我们可以接受给定的示例作为数据的代表,或者我们根本无法回答,因为总会有一个“假设”会中断解析。

1
张贴者询问如何解析不是有效JSON的异常结构。在这种情况下,@ cdleary很好地回答了这个问题。xecute:处理字符串中的逗号将需要引用或转义机制,这超出了本文的讨论范围。
Suncat2000 '16

37

这个简单的方法

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

输出

name1

为此支持,尽管如此:var string =“ {firstName:'name1',lastName:'last1',f:function(){alert('u got hacked ...')}()}”; eval('var obj'+ string)这可能会让您被黑...但是我认为它值得,因为它在某些情况下是唯一可行的。
科迪

12

如果您使用的是JQuery:

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

记住:评估是邪恶的!:D


7
jQuery使用evalglobalEval: /** code **/ window[ "eval" ].call( window, data ); /** more code **/
2013年

12
问题所有者提供的字符串不是有效的JSON字符串。因此,这段代码毫无用处……
xecute 2013年

是的,如果在“受控”环境下使用eval,则eval并不是邪恶的(除了文件,网络或用户输入之类的外部数据,在任何情况下,如果未“过滤/验证”,它可能很危险)。
mzalazar

10

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

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

10

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

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


8

如果您有类似的字符串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的输入,结果输出是什么?
not2qubit

很公平。通常,我没有时间详细说明内容,而只是丢下一些有用的内容(特别是在我遇到相同的SO问题的情况下),但是我很生气。
corysimmons

1
这绝对是最优雅的解决方案,并且实际上可以回答很多其他问题,而无需回答其他问题。并感谢您的解释!
凯茜·哈

4

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

有一个这样的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-属性,而不是像某些框架/库那样创建伪自定义属性。
约翰(John)

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

2
只是一个想法-代替第二个split(':'),您可以使用indexOf(“:”)通过FIRST冒号“手动”分割字符串,然后将字符串的一部分视为该冒号作为键,其余部分视为冒号,价值。
Ondrej Vencovsky 2015年

2

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

好的部分是它包含no evalno new Function,使用非常安全。


1

这是通用代码,无论您输入的内容有多长,但如果存在:

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)

0

就你而言

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

3
应不惜一切代价避免评估。
亚历克斯

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

“对象”数组将具有所有对象


0

我知道这是一篇过时的文章,但是没有找到正确的答案。

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获取值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.