Рядок об'єкта в JS


190

У мене є рядок як

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

тепер мені потрібен один об'єкт obj, такий

obj = {firstName:name1, lastName:last1}

Як я можу це зробити в JS?


1
Чи є значення name1 та last1 string або ідентифікатори, визначені в інших місцях?
cdleary

1
Потрібно більше даних ... що ви робите, якщо ключ або значення містять кому або двокрапку?
Бред

Якщо ваш рядок не форматується як JSON, можливо, вам доведеться використовувати RegEp для обробника.
bitfishxyz

Відповіді:


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

2
Це правда, проте строго кажучи функції не повинні бути в жодних об'єктах JSON. Для цього у вас є RPC тощо, або, якщо ви хочете, ви можете передати прототип функції в json і зробити це evalпізніше.
Матей

36
Я зовсім не боюся відповіді на запитання. Було б чудово, якби кожен змінив питання на відповідь. Як ти розбираєш "firstName: name1, lastName: last1"? не '{"привіт": "світ"} ".
Ноель Абрахамс

33
Це не відповідає на питання, я не знаю, чому в ньому так багато відгуків. Опитуючий (і я сам, я гуглив і опинився тут), мають дані, які не відповідають стандарту JSON, тому їх неможливо проаналізувати.
Аарон Грінвальд

1
var a = "firstName: name1, lastName: last1"; JSON.parse ('{' + a + '}') видає помилку.
Аарон Грінвальд

73

Ваша рядок схожа на рядок JSON без фігурних дужок.

Це має працювати тоді:

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

22
це потенційна дірка безпеки. Я б не рекомендував цей метод взагалі.
Бретон

65
Це залежить, звідки беруться дані. Деякі люди одержимі безпекою. Якщо ви контролюєте свої дані, ви можете бути більш прагматичними у пошуку рішень. Або у вас між кухнею та вітальнею двері, захищені від вибуху?
Філіп Лейбаерт

13
Це не працює. Це дає вам помилку 'SyntaxError: Неочікуваний маркер:' . Я перевірив це в Chrome.
Нямбаа

12
Для вирішення потрібні дужки навколо нього:obj = eval('({' + str + '})');
Крістіан

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/… Вибачте, не можу знайти іншого способу зв’язатися з вами, окрім коментарів до відповідей ур
Джейсон

1
Префект посаду. Ця відповідь використовує основи JavaScript дуже зрозумілі, і тому він повинен працювати в кожному браузері
Мішель

Я знайшов такий підхід вдалим початком, тому відповідь була корисною. Однак у xecute є дійсна точка, що вона не вміщує рядки, у яких можуть бути коми. Ви можете піти по шляху узгодження лапок, якщо ваш код повинен обробляти рядки з комами, але ви все одно не збираєтеся зафіксувати випадки, коли цитати уникнути. Просто реалізуйте те, що вам потрібно, а потім зупиніться.
Патрік Грем

1
У питанні розбору тексту, представленого запитувачем, питання "що робити" є марними. Ми можемо прийняти даний приклад як представник даних або просто не можемо відповісти, оскільки завжди може бути "що робити", що порушить аналіз.

1
Плакат запитав про те, як розібрати незвичайну структуру, яка не була дійсною JSON. @cdleary дуже добре відповів на питання за обставин. xecute: обробка комою в рядку вимагає механізму цитування чи виходу поза межі цього обговорення.
Suncat2000

37

Цей простий спосіб ...

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

вихід

name1

Підтвердьте це, ALTHOUGH: var string = "{firstName: 'name1', lastName: 'last1', f: function () {alert ('вас зламали ...')} ()}"; 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 використовує eval. globalEval: /** code **/ window[ "eval" ].call( window, data ); /** more code **/
SomeShinyObject

12
Рядок, наданий власником запитань, не є дійсним рядком JSON. Отже, цей код марний ...
xecute

так, eval не є злом, якщо ви використовуєте його в "контрольованому" середовищі (що завгодно, крім зовнішніх даних, таких як файли, мережа або користувальницькі дані, у таких випадках це може бути небезпечно, якщо не "відфільтровано / перевірено").
mzalazar

11

Оскільки метод JSON.parse () вимагає, щоб ключі об'єктів були вкладені в лапки, щоб він працював правильно, спочатку нам доведеться перетворити рядок у формат 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


10

Вам потрібно використовувати JSON.parse () для перетворення рядка в об’єкт:

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

9

Якщо у вас є такий рядок, як 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;
  }, {});

Завдяки niggler в #javascript за це.

Оновити пояснення:

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!

Це абсолютно незрозуміла відповідь для пересічного читача. Чи можете ви пояснити, що робить кожен рядок? І який результат, враховуючи вхід ОП?
not2qubit

1
Досить справедливо. Як правило, я не встигаю деталізувати речі, і я просто відкидаю корисні шматочки (зокрема на випадок, якщо я зіткнувся з тим самим точним питанням ТАК вниз по дорозі), але я зрозумів
corysimmons

2
Це, безумовно, найелегантніше рішення і насправді відповідає на питання на відміну від багатьох інших відповідей. І дякую за пояснення!
Cathy Ha

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-атрибута замість створення атрибутів псевдо-користування, як-от деякі рамки / бібліотеки.
Іван

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
Просто ідея - замість другого розколу (':') ви могли розділити рядок "вручну" ПЕРШОЮ колоною за допомогою indexOf (":") і розглядати частину рядка до цієї двокрапки як ключ, а решту після двокрапки як значення.
Ондрей Венцовський

2

Це універсальний код, незалежно від того, наскільки довгий ваш вхід, але в тій же схемі, якщо є: роздільник :)

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)

2

Я використовую JSON5 , і він працює досить добре.

Гарна частина полягає в тому, що вона не містить evalі ні new Function , дуже безпечна у використанні.


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
eval слід уникати будь-якою ціною.
Олексій

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.firstNameта obj.lastNameотримувати значення, як ви могли б робити нормально з об'єктом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.