สตริงไปยังวัตถุใน JS


190

ฉันมีสายเป็น

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

ตอนนี้ฉันต้องการวัตถุหนึ่ง obj เช่นนั้น

obj = {firstName:name1, lastName:last1}

ฉันจะทำสิ่งนี้ใน JS ได้อย่างไร


1
name1 และ last1 มีค่าสตริงหรือตัวระบุที่กำหนดไว้ที่อื่นหรือไม่?
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ภายหลัง
Matej

36
ไม่ตอบคำถามเลยฉันกลัว มันจะยอดเยี่ยมถ้าทุกคนเปลี่ยนคำถามเพื่อให้เหมาะกับคำตอบ คุณแยกวิเคราะห์ "firstName: name1, lastName: last1" ได้อย่างไร ไม่ใช่ '{"hello": "world"}'
Noel Abrahams

33
นี่ไม่ตอบคำถามฉันไม่รู้ว่าทำไมมันมี upvotes มากมาย ผู้ถาม (และตัวฉันเองฉันทำ Google และจบที่นี่) มีข้อมูลที่ไม่เป็นไปตามมาตรฐานของ JSON ดังนั้นจึงไม่สามารถแยกวิเคราะห์ได้
Aaron Greenwald

1
var a = "firstName: name1, lastName: last1"; JSON.parse ('{' + a + '}') ส่งข้อผิดพลาด
Aaron Greenwald

73

สตริงของคุณดูเหมือนสตริง JSON ที่ไม่มีเครื่องหมายปีกกา

สิ่งนี้ควรใช้งานได้แล้ว:

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

22
นี่เป็นช่องโหว่ความปลอดภัย ฉันจะไม่แนะนำวิธีนี้เลย
เบรอตง

65
ขึ้นอยู่กับว่าข้อมูลมาจากไหน บางคนหมกมุ่นอยู่กับความปลอดภัย หากคุณควบคุมข้อมูลของคุณคุณสามารถจริงจังในการหาวิธีแก้ปัญหา หรือคุณมีประตูกันขโมยระหว่างห้องครัวและห้องนั่งเล่นของคุณ?
Philippe Leybaert

13
มันไม่ทำงาน มันทำให้คุณมีข้อผิดพลาด'SyntaxError: โทเค็นที่ไม่คาดคิด:' ฉันตรวจสอบแล้วใน Chrome
Nyambaa

12
การแก้ปัญหาต้องใช้วงเล็บล้อมรอบ:obj = eval('({' + str + '})');
คริสเตียน

12
prc322: ทุกคนรู้ว่า eval () ไม่ปลอดภัยมาก (และนั่นคือการพูดเกินจริง) แต่การใช้ eval () เป็นคำตอบที่ถูกต้องสำหรับคำถามข้างต้นเพราะสตริงอินพุตไม่ใช่สตริง JSON ที่ถูกต้องและอินพุตสตริงอ้างอิงตัวแปรอื่น ๆ โดยชื่อ.
Philippe Leybaert

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/…ขออภัยไม่สามารถหาวิธีอื่นในการติดต่อคุณยกเว้นการแสดงความคิดเห็นผ่านคำตอบของคุณ
Jason

1
นายอำเภอโพสต์ คำตอบนี้ใช้พื้นฐานของ JavaScript ที่ชัดเจนมากและควรใช้กับเบราว์เซอร์ทุกตัว
Michel

ฉันพบว่าวิธีนี้เป็นการเริ่มต้นที่ดีดังนั้นคำตอบก็มีประโยชน์ อย่างไรก็ตาม xecute มีจุดที่ถูกต้องซึ่งไม่รองรับสตริงที่อาจมีเครื่องหมายจุลภาค คุณสามารถลงไปตามเส้นทางของคำพูดที่ตรงกันหากรหัสของคุณต้องการจัดการสตริงด้วยเครื่องหมายจุลภาค แต่คุณยังคงไม่ทราบถึงกรณีที่เครื่องหมายคำพูดหนี เพียงใช้สิ่งที่คุณต้องการจากนั้นหยุด
Patrick Graham

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', นามสกุล: 'last1', f: function () {การแจ้งเตือน ('คุณถูกแฮ็ค ... ')} ()}"; eval ('var obj' + string) สิ่งนี้อาจทำให้คุณแฮ็ค ... แต่ฉันคิดว่ามันคุ้มค่าเพราะมันเป็นสิ่งเดียวที่ใช้งานได้ในบางกรณี
โคดี

12

หากคุณกำลังใช้ JQuery:

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

จำไว้ว่า: eval นั้นชั่วร้าย! : D


7
evalใช้ jQuery 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!

นี่เป็นคำตอบที่เข้าใจยากโดยสิ้นเชิงสำหรับผู้อ่านโดยเฉลี่ย คุณช่วยอธิบายว่าแต่ละบรรทัดทำอะไรได้บ้าง และผลลัพธ์ที่ได้คืออะไรจากอินพุตของ OP
not2qubit

1
ยุติธรรมพอสมควร โดยทั่วไปแล้วฉันไม่มีเวลาที่จะพูดถึงรายละเอียดและฉันก็ทิ้งบิตที่เป็นประโยชน์ (โดยเฉพาะในกรณีที่ฉันพบคำถาม SO ที่เหมือนกันตามถนน) แต่ฉันก็รับ
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
เพียงแค่ความคิด - แทนการแยกที่สอง (':') คุณสามารถแยกสตริง "ด้วยตนเอง" โดยโคลอน FIRST โดยใช้ indexOf (":") และพิจารณาส่วนของสตริงจนกระทั่งโคลอนนี้เป็นคีย์และส่วนที่เหลือหลังโคลอนเป็น มูลค่า.
Ondrej Vencovsky

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
ควรหลีกเลี่ยงการประเมินค่าใช้จ่ายทั้งหมด
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);
        });

อาร์เรย์ "วัตถุ" จะมีวัตถุทั้งหมด


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รับค่าตามที่คุณสามารถทำได้ตามปกติกับวัตถุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.