Chuỗi đối tượng trong JS


190

Tôi có một chuỗi như

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

bây giờ tôi cần một đối tượng obj sao cho

obj = {firstName:name1, lastName:last1}

Làm thế nào tôi có thể làm điều này trong JS?


1
Các giá trị hoặc định danh chuỗi name1 và last1 đã được xác định ở nơi khác chưa?
cdleary

1
Cần thêm dữ liệu ... bạn đang làm gì nếu khóa hoặc giá trị chứa dấu phẩy hoặc dấu hai chấm?
Brad

Nếu chuỗi của bạn không được định dạng dưới dạng JSON, bạn có thể phải sử dụng RegEp để xử lý.
bitfishxyz

Câu trả lời:


165

Trên thực tế, giải pháp tốt nhất là sử dụng JSON:

Tài liệu

JSON.parse(text[, reviver]);

Ví dụ:

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) Truyền một hàm cho 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();

sẽ không cho phép các chức năng được thông qua mặc dù
K2xL

2
Điều đó đúng, tuy nhiên, các hàm nói đúng không nên có trong bất kỳ đối tượng JSON nào .. Đối với việc bạn có RPC, v.v. hoặc nếu bạn muốn, bạn có thể chuyển nguyên mẫu của hàm cho json và thực hiện evalsau.
Matej

36
Tôi không trả lời câu hỏi nào cả. Sẽ thật tuyệt vời nếu mọi người thay đổi câu hỏi cho phù hợp với câu trả lời. Làm thế nào để bạn phân tích "FirstName: name1, lastName: last1"? không phải '{"xin chào": "thế giới"}'.
Noel Abrahams

33
Điều này không trả lời câu hỏi, tôi không biết tại sao nó có quá nhiều sự ủng hộ. Người hỏi (và bản thân tôi, tôi đã googled và kết thúc ở đây) có dữ liệu không phù hợp với tiêu chuẩn JSON nên không thể phân tích cú pháp.
Aaron Greenwald

1
var a = "firstName: name1, lastName: last1"; JSON.parse ('{' + a + '}') đưa ra lỗi.
Aaron Greenwald

73

Chuỗi của bạn trông giống như một chuỗi JSON mà không có dấu ngoặc nhọn.

Điều này sẽ làm việc sau đó:

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

22
Đây là một lỗ hổng bảo mật tiềm năng. Tôi sẽ không đề nghị phương pháp này cả.
Breton

64
Nó phụ thuộc vào nơi dữ liệu đến từ. Một số người bị ám ảnh bởi an ninh. Nếu bạn kiểm soát dữ liệu của mình, bạn có thể thực dụng hơn trong việc tìm giải pháp. Hay bạn có một cửa chống trộm giữa nhà bếp và phòng khách của bạn?
Philippe Leybaert

13
Điều đó không hiệu quả. Nó cung cấp cho bạn lỗi 'Cú phápError: Mã thông báo không mong muốn:' . Tôi đã kiểm tra nó trong Chrome.
Nyambaa

12
Giải pháp cần có dấu ngoặc đơn xung quanh nó:obj = eval('({' + str + '})');
Christian

12
prc322: Mọi người đều biết rằng eval () không an toàn lắm (và đó là cách đánh giá thấp), nhưng sử dụng eval () là câu trả lời đúng duy nhất cho câu hỏi trên vì chuỗi đầu vào không phải là chuỗi JSON hợp lệ VÀ chuỗi đầu vào tham chiếu các biến khác bằng tên.
Philippe Leybaert

50

Nếu tôi hiểu đúng:

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

Tôi giả sử rằng tên thuộc tính nằm ở bên trái dấu hai chấm và giá trị chuỗi mà nó nhận là ở bên phải.

Lưu ý đó Array.forEachlà JavaScript 1.6 - bạn có thể muốn sử dụng bộ công cụ để tương thích tối đa.


Hey Cdleary ... tôi tự hỏi nếu bạn có thể giúp tôi: stackoverflow.com/questions/9357320/... couldnt Xin lỗi tìm một cách khác để liên lạc với bạn trừ qua ý kiến về câu trả lời ur
Jason

1
Bài viết hoàn hảo. Câu trả lời này sử dụng các khái niệm cơ bản về JavaScript rất rõ ràng và do đó sẽ hoạt động trong mọi trình duyệt
Michel

Tôi thấy cách tiếp cận này là một khởi đầu tốt, vì vậy câu trả lời là hữu ích. Tuy nhiên, xecute có một điểm hợp lệ là nó không chứa các chuỗi có thể có dấu phẩy. Bạn có thể đi xuống đường dẫn của dấu ngoặc kép nếu mã của bạn cần xử lý chuỗi bằng dấu phẩy, nhưng bạn vẫn không bắt được trường hợp dấu ngoặc kép được thoát. Chỉ cần thực hiện những gì bạn cần, sau đó dừng lại.
Patrick Graham

1
Trong một câu hỏi về phân tích văn bản được trình bày bởi người hỏi, các câu hỏi về "nếu như" là vô ích. Chúng tôi có thể chấp nhận ví dụ đã cho là đại diện cho dữ liệu hoặc đơn giản là chúng tôi không thể trả lời vì luôn có thể có "điều gì xảy ra nếu" sẽ phá vỡ phân tích cú pháp.

1
Người đăng đã hỏi về cách phân tích một cấu trúc bất thường không phải là JSON hợp lệ. @cdleary trả lời câu hỏi rất hay trong hoàn cảnh. xecute: xử lý dấu phẩy trong chuỗi sẽ yêu cầu cơ chế trích dẫn hoặc thoát, ngoài phạm vi của cuộc thảo luận này.
Suncat2000

37

Cách đơn giản này ...

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

đầu ra

name1

Upvote cho điều này, ALTHOUGH: var string = "{firstName: 'name1', lastName: 'last1', f: function () {alert ('u đã bị hack ...')} ()}"; eval ('var obj' + string) Điều này có thể khiến bạn bị hack ... nhưng tôi nghĩ giá trị của nó trong khi đó là thứ duy nhất hoạt động trong một số trường hợp.
Cody

12

nếu bạn đang sử dụng JQuery:

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

HÃY NHỚ: eval là ác! : D


7
Sử dụng jQuery eval. globalEval: /** code **/ window[ "eval" ].call( window, data ); /** more code **/
Một sốShinyObject

12
Chuỗi, được cung cấp bởi chủ sở hữu câu hỏi không phải là chuỗi JSON hợp lệ. Vì vậy, mã này là vô dụng ...
xecute

có, eval không xấu nếu bạn sử dụng nó trong môi trường "được kiểm soát" (bất cứ thứ gì ngoại trừ dữ liệu ngoài như tệp, mạng hoặc đầu vào của người dùng, trong trường hợp đó có thể nguy hiểm nếu không được "lọc / xác thực").
mzalazar

10

Bạn cần sử dụng JSON.parse () để chuyển đổi Chuỗi thành Đối tượng:

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

10

Do phương thức JSON.parse () yêu cầu các khóa Object được đặt trong dấu ngoặc kép để nó hoạt động chính xác, trước tiên chúng ta phải chuyển đổi chuỗi thành chuỗi có định dạng JSON trước khi gọi phương thức 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

Điều này sẽ hoạt động ngay cả khi chuỗi có một đối tượng phức tạp (như sau) và nó vẫn sẽ chuyển đổi chính xác. Chỉ cần đảm bảo rằng chính chuỗi được đặt trong dấu ngoặc đơn.

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

Nếu bạn có một chuỗi như foo: 1, bar: 2bạn có thể chuyển đổi nó thành một obj hợp lệ với:

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

Cảm ơn niggler trong #javascript vì điều đó.

Cập nhật với lời giải thích:

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)

Tài liệu MDN khó hiểu:

Bản trình diễn: http://jsbin.com/hiduhijevu/edit?js,console

Chức năng:

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!

Đây là một câu trả lời hoàn toàn khó hiểu cho người đọc trung bình. Bạn có thể giải thích những gì từng dòng làm? Và kết quả đầu ra, đầu vào của OP là gì?
not2qubit

Đủ công bằng. Thông thường tôi không có thời gian để chi tiết các công cụ và tôi chỉ bỏ các bit hữu ích (cụ thể là trong trường hợp tôi gặp phải câu hỏi SO chính xác tương tự), nhưng tôi đã hiểu.
corysimmons

1
Đây chắc chắn là giải pháp tao nhã nhất và thực sự trả lời câu hỏi không giống như nhiều câu trả lời khác. Và cảm ơn bạn đã giải thích!
Cathy Ha

4

Tôi đã triển khai một giải pháp trong một vài dòng mã hoạt động khá đáng tin cậy.

Có một yếu tố HTML như thế này nơi tôi muốn vượt qua các tùy chọn tùy chỉnh:

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

một hàm phân tích các tùy chọn tùy chỉnh và trả về một đối tượng để sử dụng ở đâu đó:

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 để sử dụng data-thuộc tính thay vì tạo các thuộc tính giả tùy chỉnh như một số khung / thư viện.
Giăng

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

Điều này sẽ làm việc:

var fields = string.split(', '),
    fieldObject = {};

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

Tuy nhiên nó không hiệu quả. Điều gì xảy ra khi bạn có một cái gì đó như thế này:

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

split()sẽ chia 'http'. Vì vậy, tôi khuyên bạn nên sử dụng một dấu phân cách đặc biệt như ống

 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
Chỉ là một ý tưởng - thay vì phân tách thứ hai (':'), bạn có thể phân tách chuỗi "thủ công" bằng dấu hai chấm FIRST bằng cách sử dụng indexOf (":") và coi phần của chuỗi cho đến dấu hai chấm này và phần còn lại sau dấu hai chấm giá trị.
Ondrej Vencovsky

2

Tôi đang sử dụng JSON5 và nó hoạt động khá tốt.

Phần tốt là nó không chứa evalkhông new Function , rất an toàn để sử dụng.


1

Đây là mã phổ quát, cho dù đầu vào của bạn dài như thế nào nhưng trong cùng một lược đồ nếu có: dấu phân cách :)

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

Trong trường hợp của bạn

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
eval nên tránh bằng mọi giá.
Alex

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

mảng "đối tượng" sẽ có tất cả các đối tượng


0

Tôi biết đây là một bài viết cũ nhưng không thấy câu trả lời chính xác cho câu hỏi.

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

Bây giờ bạn có thể sử dụng obj.firstNameobj.lastNameđể có được các giá trị như bạn có thể làm bình thường với một đối tượng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.