String ke objek di JS

190

Saya memiliki string sebagai

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

sekarang saya butuh satu objek obj sedemikian rupa

obj = {firstName:name1, lastName:last1}

Bagaimana saya bisa melakukan ini di JS?

rahul
sumber
1
Apakah name1 dan last1 nilai atau pengidentifikasi string telah didefinisikan di tempat lain?
cdleary
1
Diperlukan lebih banyak data ... apa yang Anda lakukan jika kunci atau nilainya berisi koma atau titik dua?
Brad
Jika string Anda tidak diformat sebagai JSON, Anda mungkin harus menggunakan RegEp untuk menangani.
bitfishxyz

Jawaban:

165

Sebenarnya, solusi terbaik adalah menggunakan JSON:

Dokumentasi

JSON.parse(text[, reviver]);

Contoh:

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) Melewati fungsi ke 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();
Matej
sumber
tidak akan mengizinkan fungsi untuk diteruskan
K2xL
2
Itu benar, namun fungsi yang benar-benar berbicara tidak boleh di objek JSON .. Untuk itu Anda memiliki RPC dll, atau jika Anda mau, Anda dapat meneruskan prototipe fungsi ke json, dan lakukan evalnanti.
Matej
36
Saya tidak menjawab pertanyaan sama sekali. Akan luar biasa jika semua orang mengubah pertanyaan agar sesuai dengan jawabannya. Bagaimana Anda menguraikan "firstName: name1, lastName: last1"? bukan '{"hello": "world"}'.
Noel Abrahams
33
Ini tidak menjawab pertanyaan, saya tidak tahu mengapa ada begitu banyak upvotes. Penanya (dan saya sendiri, saya googled dan berakhir di sini) memiliki data yang tidak sesuai dengan standar JSON sehingga tidak dapat diuraikan.
Aaron Greenwald
1
var a = "firstName: name1, lastName: last1"; JSON.parse ('{' + a + '}') melempar kesalahan.
Aaron Greenwald
73

Tali Anda terlihat seperti string JSON tanpa kawat gigi keriting.

Maka ini harus bekerja:

obj = eval('({' + str + '})');
Philippe Leybaert
sumber
22
ini adalah lubang keamanan potensial. Saya tidak akan merekomendasikan metode ini sama sekali.
Breton
65
Itu tergantung dari mana data berasal. Beberapa orang terobsesi dengan keamanan. Jika Anda mengontrol data Anda, Anda bisa lebih pragmatis dalam menemukan solusi. Atau apakah Anda memiliki pintu anti-pencurian antara dapur dan ruang tamu Anda?
Philippe Leybaert
13
Itu tidak berhasil. Ini memberi Anda kesalahan 'SyntaxError: Token yang tidak terduga:' . Saya sudah memeriksanya di Chrome.
Nyambaa
12
Solusinya membutuhkan tanda kurung di sekitarnya:obj = eval('({' + str + '})');
Christian
12
prc322: Semua orang tahu bahwa eval () tidak terlalu aman (dan itu meremehkan), tetapi menggunakan eval () adalah satu-satunya jawaban yang benar untuk pertanyaan di atas karena string input bukan string JSON yang valid DAN string input referensi variabel lain dengan nama.
Philippe Leybaert
50

Jika saya mengerti dengan benar:

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

Saya berasumsi bahwa nama properti di sebelah kiri titik dua dan nilai string yang diperlukan adalah di sebelah kanan.

Perhatikan bahwa Array.forEachini JavaScript 1.6 - Anda mungkin ingin menggunakan toolkit untuk kompatibilitas maksimum.

cdleary
sumber
Hei Cdleary ... saya ingin tahu apakah Anda dapat membantu saya: stackoverflow.com/questions/9357320/... Maaf tidak dapat menemukan cara lain untuk menghubungi Anda kecuali melalui komentar pada jawaban Anda
Jason
1
Pos prefek. Jawaban ini menggunakan dasar-dasar JavaScript yang sangat jelas dan karenanya harus berfungsi di setiap browser
Michel
Saya menemukan pendekatan ini merupakan awal yang baik, jadi jawabannya bermanfaat. Namun, xecute memiliki titik valid yang tidak mengakomodasi string yang mungkin memiliki koma. Anda bisa pergi ke jalan yang cocok dengan kutipan jika kode Anda perlu menangani string dengan koma, tetapi Anda masih tidak akan menangkap kasus di mana kutipan diloloskan. Cukup terapkan apa yang Anda butuhkan, lalu berhenti.
Patrick Graham
1
Dalam pertanyaan tentang teks parsing yang disajikan oleh penanya, pertanyaan "bagaimana jika" tidak berguna. Kami dapat menerima contoh yang diberikan sebagai perwakilan data atau kami tidak bisa menjawab karena selalu ada "bagaimana jika" yang akan memecah parsing.
1
Poster itu bertanya tentang bagaimana mengurai struktur yang tidak biasa yang tidak valid JSON. @cdleary menjawab pertanyaan dengan sangat baik dalam situasi tersebut. xecute: menangani koma dalam string akan memerlukan mekanisme penawaran atau pelarian, di luar cakupan diskusi ini.
Suncat2000
37

Cara sederhana ini ...

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

keluaran

name1
Wianto Wie
sumber
Terpilih untuk ini, SELALU: var string = "{firstName: 'name1', lastName: 'last1', f: function () {alert ('u hacked ...')} ()}"; eval ('var obj' + string) Ini bisa membuat Anda diretas ... tapi saya pikir nilainya sementara karena itu satu-satunya hal yang berfungsi dalam beberapa kasus.
Cody
12

jika Anda menggunakan JQuery:

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

INGAT: eval itu jahat! : D

mzalazar
sumber
7
jQuery menggunakan eval. globalEval: /** code **/ window[ "eval" ].call( window, data ); /** more code **/
SomeShinyObject
12
String yang disediakan oleh pemilik pertanyaan bukanlah string JSON yang valid. Jadi, kode ini tidak berguna ...
xecute
ya, eval tidak jahat jika Anda menggunakannya di lingkungan "terkendali" (apa pun kecuali data eksternal seperti file, jaringan atau input pengguna, dalam hal ini bisa berbahaya jika tidak "difilter / divalidasi").
mzalazar
11

Karena metode JSON.parse () membutuhkan kunci Object yang dilampirkan dalam tanda kutip agar berfungsi dengan benar, pertama-tama kita harus mengubah string menjadi string yang diformat JSON sebelum memanggil metode 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

Ini akan berfungsi bahkan jika string memiliki objek yang kompleks (seperti yang berikut) dan masih akan dikonversi dengan benar. Pastikan saja string itu sendiri tertutup dalam tanda kutip tunggal.

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

Faisal Chishti
sumber
10

Anda perlu menggunakan JSON.parse () untuk mengonversi String menjadi Obyek:

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

Jika Anda memiliki string seperti foo: 1, bar: 2Anda dapat mengonversinya menjadi obj yang valid dengan:

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

Terima kasih kepada niggler dalam #javascript untuk itu.

Perbarui dengan penjelasan:

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)

Dokumen MDN yang membingungkan:

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

Fungsi:

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!
Corysimmons
sumber
Ini adalah jawaban yang sama sekali tidak bisa dipahami oleh pembaca rata-rata. Bisakah Anda menjelaskan apa yang dilakukan setiap baris? Dan apa output yang dihasilkan, mengingat input OP?
not2qubit
1
Cukup adil. Biasanya saya tidak punya waktu untuk merinci hal-hal dan saya hanya menjatuhkan bit membantu (khususnya jika saya mengalami pertanyaan SO yang sama persis di jalan), tapi saya mengerti.
corysimmons
2
Ini jelas merupakan solusi paling elegan dan benar-benar menjawab pertanyaan tidak seperti banyak jawaban lainnya. Dan terima kasih atas penjelasannya!
Cathy Ha
4

Saya menerapkan solusi dalam beberapa baris kode yang bekerja dengan cukup andal.

Memiliki elemen HTML seperti ini tempat saya ingin memberikan opsi khusus:

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

suatu fungsi mem-parsing opsi kustom dan mengembalikan objek untuk menggunakannya di suatu tempat:

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')));
rodu
sumber
+1 untuk menggunakan data-atribut alih-alih membuat atribut pseudo-custom seperti beberapa kerangka / pustaka.
John
3
string = "firstName:name1, lastName:last1";

Ini akan berhasil:

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

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

Namun itu tidak efisien. Apa yang terjadi ketika Anda memiliki sesuatu seperti ini:

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

split()akan membagi 'http'. Jadi saya sarankan Anda menggunakan pembatas khusus seperti pipa

 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];
       });
    }
Emeka Mbah
sumber
2
Hanya sebuah gagasan - alih-alih pemisahan kedua (':') Anda dapat membagi string "secara manual" dengan titik dua PERTAMA menggunakan indexOf (":") dan mempertimbangkan bagian dari string sampai titik dua ini sebagai kunci dan sisanya setelah titik dua sebagai nilai.
Ondrej Vencovsky
2

Ini adalah kode universal, tidak peduli seberapa panjang input Anda tetapi dalam skema yang sama jika ada: pemisah :)

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)
panatoni
sumber
2

Saya menggunakan JSON5 , dan berfungsi dengan baik.

Bagian yang baik adalah mengandung tidak ada eval dan tidak ada new Function , sangat aman untuk digunakan.

James Yang
sumber
0

Dalam kasus Anda

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]);
}
Vahag Chakhoyan
sumber
3
eval harus dihindari di semua biaya.
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);
        });

"Objek" array akan memiliki semua objek

datanglah
sumber
0

Saya tahu ini adalah posting lama tetapi tidak melihat jawaban yang benar untuk pertanyaan itu.

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

Sekarang Anda dapat menggunakan obj.firstNamedan obj.lastNameuntuk mendapatkan nilai-nilai yang dapat Anda lakukan secara normal dengan objek.

Raoul
sumber