JS'de nesneye dize


190

Olarak bir dizem var

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

şimdi bir nesneye ihtiyacım var ki öyle ki

obj = {firstName:name1, lastName:last1}

Bunu JS'de nasıl yapabilirim?


1
Name1 ve last1 dize değerleri veya başka bir yerde tanımlanmış tanımlayıcılar mı?
cdleary

1
Daha fazla veri gerekiyor ... Anahtar veya değer virgül veya iki nokta üst üste işaret içeriyorsa ne yapıyorsunuz?
Brad

Dizeniz JSON olarak biçimlendirilmemişse, işleyici için RegEp kullanmanız gerekebilir.
bitfishxyz

Yanıtlar:


165

Aslında, en iyi çözüm JSON kullanmaktır:

belgeleme

JSON.parse(text[, reviver]);

Örnekler:

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) Bir işlevi JSON'a geçirmek

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

fonksiyonların geçmesine izin vermeyecek
K2xL

2
Bu doğrudur, ancak kesinlikle konuşan işlevler herhangi bir JSON nesnesinde olmamalıdır. Bunun için RPC vb. Var veya isterseniz, bir işlevin prototipini json'a iletebilir ve evaldaha sonra yapabilirsiniz.
Matej

36
Korkarım soruya hiç cevap vermiyor. Herkes soruyu cevaba uyacak şekilde değiştirirse harika olurdu. "FirstName: name1, lastName: last1" nasıl ayrıştırılır? '{"merhaba": "dünya"}' değil.
Noel Abrahams

33
Bu soruya cevap vermiyor, neden bu kadar çok oyu olduğunu bilmiyorum. Sorgulayan (ve kendimi googled ve burada sona erdi) JSON standardına uymayan verilerle ayrıştırılamaz.
Aaron Greenwald

1
var a = "adAdı: ad1, sonAd: son1"; JSON.parse ('{' + a + '}') bir hata atar.
Aaron Greenwald

73

Dizeniz, süslü parantezleri olmayan bir JSON dizesine benziyor.

Bu sonra çalışmalıdır:

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

22
bu potansiyel bir güvenlik açığıdır. Bu yöntemi hiç tavsiye etmem.
Breton

65
Verilerin nereden geldiğine bağlıdır. Bazı insanlar güvenlik konusunda takıntılıdır. Verilerinizi kontrol ederseniz, çözüm bulma konusunda daha pragmatik olabilirsiniz. Yoksa mutfağınız ile oturma odanız arasında hırsızlığa karşı korumalı bir kapınız var mı?
Philippe Leybaert

13
Bu işe yaramıyor. Size 'SyntaxError: Beklenmeyen simge:' hatası veriyor . Chrome'da kontrol ettim.
Nyambaa

12
Çözümün etrafında parantez gerekiyor:obj = eval('({' + str + '})');
Christian

12
prc322: Herkes eval () işlevinin çok güvenli olmadığını bilir (ve bu bir understatement), ancak eval () kullanmak yukarıdaki soruya verilen tek doğru cevaptır, çünkü giriş dizesi geçerli bir JSON dizesi değildir ve giriş dizesi diğer değişkenlere başvurur isimle.
Philippe Leybaert

50

Doğru anlıyorsam:

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

Özellik adı iki nokta üst üste sol ve varsa dize değeri sağda olduğunu varsayalım.

Array.forEachJavaScript 1.6 olduğunu unutmayın - maksimum uyumluluk için bir araç takımı kullanmak isteyebilirsiniz.


Hey Cdleary ... bana yardım edebilir misin acaba: stackoverflow.com/questions/9357320/… Üzgünüm ur cevapları hakkında yorumlarınız dışında sizinle iletişim kurmak için başka bir yol bulamadık
Jason

1
Kaymakam posta. Bu cevap JavaScript'in temellerini çok açık kullanır ve bu nedenle her tarayıcıda çalışır
Michel

Bu yaklaşımın iyi bir başlangıç ​​olduğunu gördüm, bu yüzden cevap faydalı oldu. Ancak, xecute geçerli bir noktaya sahip olabilir ve virgül olabilecek dizeleri barındırmaz. Kodunuzun dizeleri virgülle işlemesi gerekiyorsa, eşleşen tırnak yolundan gidebilirsiniz, ancak yine de tırnaklardan kaçan durumları yakalamayacaksınız. Sadece ihtiyacınız olanı uygulayın, sonra durun.
Patrick Graham

1
Asker tarafından sunulan metni ayrıştırma sorusunda, "ya" sorusu işe yaramaz. Verilen örneği verinin temsili olarak kabul edebiliriz ya da ayrışmayı kıracak bir "eğer" her zaman olabileceğinden cevap veremeyiz .

1
Poster, geçerli JSON olmayan alışılmadık bir yapının nasıl ayrıştırılacağını sordu. @cdleary koşullar altında soruyu çok iyi yanıtladı. xecute: bir dizede virgül kullanmak, bu tartışmanın kapsamı dışında bir alıntı veya kaçış mekanizması gerektirir.
Suncat2000

37

Bu basit yol ...

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

çıktı

name1

Bunun için oy verin, ALTHOUGH: var string = "{firstName: 'name1', lastName: 'last1', f: function () {alert ('u got hacked ...')} ()}"; eval ('var obj' + string) Bu size hack olabilir ... ama ben onun değer iken düşünüyorum çünkü bazı durumlarda çalışan tek şey.
Cody

12

JQuery kullanıyorsanız:

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

UNUTMAYIN: eval kötüdür! : D


7
jQuery kullanır eval. globalEval: /** code **/ window[ "eval" ].call( window, data ); /** more code **/
SomeShinyObject

12
Soru sahibi tarafından sağlanan dize, geçerli bir JSON dizesi değil. Yani, bu kod işe yaramaz ...
xecute

evet, eval "kontrollü" bir ortamda kullanırsanız kötü değildir (dosya, ağ veya kullanıcı girişi gibi harici veriler dışında herhangi bir şey, bu durumda "filtrelenmiş / doğrulanmamış" değilse tehlikeli olabilir).
mzalazar

11

JSON.parse () yöntemi, düzgün çalışması için Nesne anahtarlarının tırnak işaretleri içine alınmasını gerektirdiğinden, JSON.parse () yöntemini çağırmadan önce dizeyi JSON biçimli bir dizeye dönüştürmeliyiz.

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

Bu, dize karmaşık bir nesneye (aşağıdakine benzer) sahip olsa bile işe yarar ve yine de doğru şekilde dönüştürülür. Dizenin kendisinin tek tırnak içine alındığından emin olun.

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

String'i bir nesneye dönüştürmek için JSON.parse () kullanmanız gerekir:

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

9

Gibi bir dizeniz foo: 1, bar: 2varsa, bunu geçerli bir objeye dönüştürebilirsiniz:

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

Bunun için #javascript'teki niggler'a teşekkürler.

Açıklamalarla güncelleme:

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)

Kafa karıştırıcı MDN belgeleri:

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

İşlev:

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!

Bu, ortalama okuyucu için tamamen anlaşılmaz bir cevaptır. Her satırın ne yaptığını açıklayabilir misiniz? Ve OP'nin girdisi göz önüne alındığında elde edilen çıktı nedir?
not2qubit

1
Yeterince adil. Genellikle bir şeyler detay için zamanım yok ve ben sadece (özellikle yolda aynı aynı SO soruya koşmak durumunda) yararlı bitleri bırakarak, ama ben gotchu.
corysimmons

2
Bu kesinlikle en zarif çözümdür ve aslında diğer birçok cevaptan farklı olarak soruyu cevaplar. Ve açıklama için teşekkürler!
Cathy Ha

4

Oldukça güvenilir çalışan birkaç kod satırında bir çözüm uyguladım.

Özel seçenekleri iletmek istediğim gibi bir HTML öğesine sahip olmak:

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

bir işlev özel seçenekleri ayrıştırır ve bunu bir yerde kullanmak için bir nesne döndürür:

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

data-Bazı çerçeveler / kütüphaneler gibi sözde özel öznitelikler oluşturmak yerine özniteliği kullanmak için +1 .
John

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

Bu çalışacak:

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

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

Ancak verimli değil. Böyle bir şey olduğunda ne olur:

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

split()'http'yi böler. Bu yüzden boru gibi özel bir ayırıcı kullanmanızı öneririm

 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
Sadece bir fikir - ikinci bölme (':') yerine, "manuel" dizesini indexOf (":") kullanarak FIRST kolonuna bölebilir ve dizenin bu iki nokta üst üste ve iki nokta üst üste işaretinden sonra kalan kısmını düşünebilirsiniz. değer.
Ondrej Vencovsky

2

Bu, evrensel koddur, girişiniz ne kadar uzun olursa olsun, aynı şemada: ayırıcı :)

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 kullanıyorum ve oldukça iyi çalışıyor.

İyi kısmı, hayır eval ve hayır new Function , kullanımı çok güvenli olmasıdır.


0

Senin durumunda

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 her ne pahasına kaçınılmalıdır.
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);
        });

"objects" dizisi tüm nesnelere sahip olacak


0

Bunun eski bir gönderi olduğunu biliyorum, ancak soru için doğru cevabı görmedim.

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

Artık bir nesneyle normalde yapabileceğiniz gibi değerleri almak için obj.firstNameve tuşlarını kullanabilirsiniz obj.lastName.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.