Рядок об'єкта в 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.