การเปลี่ยนสตริง JSON ให้เป็นวัตถุได้อย่างปลอดภัย


1335

ด้วยสตริงข้อมูล JSON ฉันจะเปลี่ยนสตริงนั้นให้เป็นวัตถุ JavaScript ได้อย่างไร

เห็นได้ชัดว่าฉันสามารถทำสิ่งนี้อย่างไม่ปลอดภัยกับสิ่งที่ชอบ:

var obj = eval("(" + json + ')');

แต่นั่นทำให้ฉันมีความเสี่ยงต่อสตริง JSON ที่มีรหัสอื่นซึ่งดูเหมือนว่าอันตรายมากที่จะประเมินได้ง่าย


77
ในภาษาส่วนใหญ่ eval มีความเสี่ยงเพิ่มเติม Eval เปิดประตูให้แฮกเกอร์ใช้ประโยชน์ อย่างไรก็ตามจำไว้ว่าจาวาสคริปต์ทั้งหมดทำงานบนไคลเอนต์ คาดว่ามันจะถูกเปลี่ยนโดยแฮกเกอร์ พวกเขาสามารถ EVAL สิ่งที่พวกเขาต้องการเพียงแค่ใช้คอนโซล คุณต้องสร้างการป้องกันทางฝั่งเซิร์ฟเวอร์
Beachhouse

19
ตกลงตอนนี้เป็นปี 2014 และคุณไม่ควรใช้evalเพื่อแยกสตริง JSON เพราะคุณจะเปิดเผยรหัสของคุณเป็น "การฉีดรหัส" ใช้JSON.parse(yourString)แทน
แดเนียล

ข้อมูล JSON เป็นตัวอักษรหรือไม่
shanechiu

@shanechiu: ถ้าคุณหมายถึงประเภทข้อมูลเซนต์คิตส์และเนวิสใช่มันเป็น เป็นเพียงสตริงที่มีไวยากรณ์คีย์ - ค่าอยู่ในนั้น
0zkr PM

คำตอบ:


1961

JSON.parse(jsonString) เป็นแนวทาง JavaScript ที่บริสุทธิ์ตราบใดที่คุณสามารถรับประกันเบราว์เซอร์ที่ทันสมัยพอสมควร


74
ฉันค่อนข้างมั่นใจว่าปลอดภัยสำหรับ Node.js
Stephen

76
@vsync คุณรู้ว่านี่เป็นเพียงคำตอบของจาวาสคริปต์เพียวเท่านั้น ... ถ้าคุณอ่านคำอธิบายของแท็กจาวาสคริปต์คุณจะเห็นสิ่งนี้ ... " นอกจากจะรวมแท็กสำหรับกรอบงาน / ไลบรารีไว้ด้วย คาดว่า ".. ฉันให้+1นี้เพื่อเป็นคำตอบเดียวของ javascript ...
iConnor


12
หากคุณกำลังทำ NodeJS ไม่มีทางที่ฉันจะโหลด jQuery เพียงเพื่อแยกวิเคราะห์ jsonString เป็นวัตถุ JSON โหวตขึ้นจากคำตอบของ Jonathan
Antony

6
ตามลิงค์นี้ได้รับการสนับสนุนโดย IE8 + แม้ว่ามันจะพูดว่า:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

วิธีการ jQuery เลิกใช้แล้ว ใช้วิธีนี้แทน:

let jsonObject = JSON.parse(jsonString);

คำตอบเดิมโดยใช้ฟังก์ชัน jQuery ที่เลิกใช้แล้ว :

หากคุณใช้ jQuery ให้ใช้:

jQuery.parseJSON( jsonString );

เป็นสิ่งที่คุณกำลังมองหา (ดูเอกสาร jQuery )


7
มีเหตุผลที่จะใช้สิ่งนี้ผ่าน JSON.parse () หรือไม่?
Jon

8
jQuery.parseJSONค่าเริ่มต้นที่จะใช้JSON.parseหากมีอยู่ดังนั้นเหตุผลเดียวที่จะใช้สิ่งนี้มากกว่าของจริงคือหากคุณต้องการทางเลือกสำหรับ <IE7 มันเปลี่ยนไปแล้วใน jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren

9
อัปเดต 2016: ตั้งแต่ jQuery 3.0, $ .parseJSONเลิกใช้แล้วและคุณควรใช้เมธอด JSON.parse ดั้งเดิมแทน
jkdev

159

คำตอบนี้สำหรับ IE <7 สำหรับเบราว์เซอร์ที่ทันสมัยตรวจสอบคำตอบของโจนาธานข้างต้น

คำตอบนี้ล้าสมัยและคำตอบที่โจนาธานข้างต้น ( JSON.parse(jsonString)) ในขณะนี้คือคำตอบที่ดีที่สุด

JSON.orgมีตัวแยกวิเคราะห์ JSON สำหรับหลายภาษารวมถึงสี่ตัวที่แตกต่างกันสำหรับ JavaScript ฉันเชื่อว่าคนส่วนใหญ่จะพิจารณาการใช้งาน goto ของjson2.js


24
ฉันหวังว่าผู้คนจะหยุดลงคะแนนคำตอบนี้ มันถูกต้องเมื่อโพสต์ในปี 2008 เพียงอัปโหลดใหม่
John

22
หากคำตอบล้าสมัยแล้วให้ลองทำการปรับปรุง
Sotirios Delimanolis

2
สำหรับ IE <8 คุณต้องใช้สิ่งนี้
Mahmoodvcs

74

ใช้ตัวอย่างโค้ดแบบง่ายใน " JSON.parse () ":

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

และย้อนกลับ:

var str = JSON.stringify(arr);

23

ผมไม่แน่ใจว่าเกี่ยวกับวิธีการอื่น ๆ ที่จะทำมัน แต่ที่นี่เป็นวิธีที่คุณทำมันในชิ้นงานทดลอง (JSON กวดวิชา)

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

การโทรevalJSON()ด้วย true เป็นอาร์กิวเมนต์ทำให้ sanitizes สตริงที่เข้ามา


22

นี่น่าจะเป็นปัญหา:

การป้อนข้อมูลที่ได้รับผ่านทางอาแจ็กซ์ WebSocket ฯลฯ และมันจะเป็นในรูปแบบ String JSON.parsableแต่คุณจำเป็นต้องรู้ว่ามันเป็น touble คือถ้าคุณมักจะเรียกใช้ผ่านJSON.parseโปรแกรมอาจจะยังคง "ประสบความสำเร็จ" "Error: unexpected token 'x'"แต่คุณจะยังคงเห็นข้อผิดพลาดในคอนโซลที่มีหวั่น

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

NO ปัญหาคือคุณคาดหวังว่าวัตถุ JSON และสามารถจบลงด้วย(function(){ postCookiesToHostileServer(); }());หรือแม้กระทั่งสิ่งที่น่ารังเกียจในบริบทของโหนด
Yaur

JSON.parse ขัดอินพุตของฟังก์ชัน (ซึ่งในกรณีนี้จะไม่ช่วยเป็นวัตถุ IIF ->) ดูเหมือนว่าวิธีที่ดีที่สุดที่จะไปเกี่ยวกับเรื่องนี้คือลอง / จับ (ดูการแก้ไข)
Cody

18

หากคุณใช้jQueryคุณสามารถใช้:

$.getJSON(url, function(data) { });

จากนั้นคุณสามารถทำสิ่งต่าง ๆ เช่น

data.key1.something
data.key1.something_else

เป็นต้น


คุณกำลังใช้ jQuery ใช่ไหม?
Alexandre C.

15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

การเรียกกลับถูกส่งผ่านข้อมูลที่ส่งคืนซึ่งจะเป็นวัตถุ JavaScript หรืออาร์เรย์ตามที่กำหนดโดยโครงสร้าง JSON และแยกวิเคราะห์โดยใช้$.parseJSON()วิธีการ


12

เพื่อความสนุกสนานนี่คือวิธีการใช้ฟังก์ชั่น:

 jsonObject = (new Function('return ' + jsonFormatData))()

1
วิธีการที่น่าสนใจฉันไม่แน่ใจว่าฉันจะใช้สิ่งนี้กับ JSON.Parse แต่มันดีที่เห็นคนที่คิดนอกกรอบ

5
สิ่งนี้คล้ายกับการใช้evalเพื่อทำและไม่ปลอดภัย : P
Florrie

7
สิ่งนี้มีข้อเสียทั้งหมดในการใช้งานevalแต่มีความซับซ้อนและยากกว่าสำหรับผู้ดูแลที่จะเข้าใจ
เควนติน

9

การใช้JSON.parseน่าจะเป็นวิธีที่ดีที่สุด

นี่คือตัวอย่างการสาธิตสด

var jsonRes = '{ "students" : [' +
          '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +
          '{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +
          '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';
var studentObject = JSON.parse(jsonRes);

9

วิธีที่ง่ายที่สุดโดยใช้parse()วิธีการ:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

จากนั้นคุณสามารถรับค่าขององค์ประกอบ JSON ตัวอย่างเช่น:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

การใช้jQueryตามที่อธิบายไว้ในjQuery.parseJSON()เอกสารประกอบ:

JSON.parse(jsonString);

9

ลองใช้วิธีการกับวัตถุข้อมูลนี้ เช่น: Data='{result:true,count:1}'

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

วิธีนี้ช่วยใน Nodejs จริงๆเมื่อคุณทำงานกับการเขียนโปรแกรมพอร์ตอนุกรม


มันเป็นเรื่องตลกว่าผู้คนกำลังจับจ้องไปที่ "EVAL เป็นความชั่วร้าย" และพวกเขาจะทำอะไรที่จะหลีกเลี่ยงได้แม้กระทั่งเรื่องการเขียน EVAL ฟังก์ชันการทำงานทั้งหมด ..
diynevala

ฉันทามตินี้เป็นวิธีที่ปลอดภัยเปลี่ยนสตริงเป็นวัตถุ JSON หรือไม่ ฉันสามารถใช้สิ่งนี้ได้เนื่องจากไม่จำเป็นต้องมีการนำเข้า js เพิ่มเติม
Whome

1
วิธีใดก็ตามที่ใช้evalหรือFunctionมีความเสี่ยงเท่ากัน
Slai

undefined; function bye() {...} bye();
Salvioner

5

ฉันพบวิธีที่ "ดีกว่า":

ใน CoffeeScript:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

ใน Javascript:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

4

การแยกวิเคราะห์ JSON เป็นความเจ็บปวดเสมอ หากอินพุตไม่เป็นไปตามที่คาดไว้มันจะพ่นข้อผิดพลาดและขัดข้องในสิ่งที่คุณกำลังทำ

คุณสามารถใช้ฟังก์ชั่นเล็ก ๆ ต่อไปนี้เพื่อแยกวิเคราะห์อินพุตของคุณได้อย่างปลอดภัย มันจะเปลี่ยนวัตถุเสมอแม้ว่าอินพุตไม่ถูกต้องหรือเป็นวัตถุที่ดีกว่าสำหรับกรณีส่วนใหญ่อยู่แล้ว:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};

Object.prototype.toString.call(input) === '[object Object]'ควรเป็นtypeof input === 'object'IMO
Serge K.

การป้อนค่า typeof จะส่งคืนวัตถุเป็นโมฆะและอาร์เรย์เช่นกัน ดังนั้นจึงไม่ใช่วิธีที่ปลอดภัยในการทำเช่นนี้
Tahsin Turkoz

คุณได้ครอบคลุมnullกรณีก่อนหน้านี้และอาร์เรย์เป็นวัตถุ instanceofหากคุณต้องการที่จะทดสอบว่าคุณสามารถใช้ ยิ่งไปกว่านั้นถ้าคุณให้ฟังก์ชั่นนี้Arrayมันจะจับและreturn defเมื่อมันสามารถคืนอาเรย์ที่ดีที่สุดได้อย่างสมบูรณ์แบบ
Serge K.

ความคิดเห็นของฉันเกี่ยวกับสามัญสำนึกในขณะที่จับวัตถุ ฟังก์ชั่นของฉันสามารถป้องกันได้หลายอย่าง แต่การใช้อินพุต type ไม่ใช่วิธีที่ต้องการในการตรวจจับวัตถุโดยทั่วไป
Tahsin Turkoz

IMO สามัญสำนึกไม่ได้ใช้toString()วิธีการตรวจสอบว่าตัวแปรเป็นวัตถุหรือไม่ ดูAngularJS , jQuery , Underscoreหรือแม้แต่devs
Serge K.


3

หากเรามีสตริงเช่นนี้:

"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"

จากนั้นเราสามารถใช้JSON.parseสองครั้งเพื่อแปลงสตริงนี้เป็นวัตถุ JSON:

var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
var jsonString= JSON.parse(sampleString)
var jsonObject= JSON.parse(jsonString)

และเราสามารถดึงค่าจากวัตถุ JSON โดยใช้:

// instead of last JSON.parse:
var { status, token } = JSON.parse(jsonString);

ผลลัพธ์จะเป็น:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() แปลงสตริง JSON ใด ๆ ที่ส่งผ่านไปยังฟังก์ชันให้เป็นวัตถุ JSON

เพื่อให้เข้าใจได้ดีขึ้นให้กดF12เพื่อเปิด "ตรวจสอบองค์ประกอบ" ในเบราว์เซอร์ของคุณและไปที่คอนโซลเพื่อเขียนคำสั่งต่อไปนี้:

var response = '{"result":true,"count":1}'; //sample json object(string form)
JSON.parse(response); //converts passed string to JSON Object.

ตอนนี้รันคำสั่ง:

console.log(JSON.parse(response));

{result: true, count: 1}คุณจะได้รับการส่งออกในฐานะที่เป็นวัตถุ

ในการใช้วัตถุนั้นคุณสามารถกำหนดให้ตัวแปรอาจจะobj:

var obj = JSON.parse(response);

โดยการใช้objและตัวดำเนินการ dot ( .) คุณสามารถเข้าถึงคุณสมบัติของวัตถุ JSON

ลองเรียกใช้คำสั่ง:

console.log(obj.result);

3

เอกสารอย่างเป็นทางการ :

JSON.parse()วิธีการแยกวิเคราะห์สตริง JSON ที่สร้างมูลค่า JavaScript หรือวัตถุอธิบายโดยสตริง ตัวเลือกreviverฟังก์ชั่นสามารถให้การดำเนินการเปลี่ยนแปลงบนวัตถุที่เกิดขึ้นก่อนที่มันจะถูกส่งกลับ

ไวยากรณ์:

JSON.parse(text[, reviver])

พารามิเตอร์:

text : สตริงที่จะแยกวิเคราะห์เป็น JSON ดูอ็อบเจ็กต์ JSON สำหรับคำอธิบายของไวยากรณ์ JSON

reviver (optional) : หากฟังก์ชั่นสิ่งนี้จะกำหนดวิธีการแปลงค่าเดิมที่ผลิตโดยการแยกวิเคราะห์ก่อนที่จะถูกส่งกลับ

ค่าส่งคืน

วัตถุที่สอดคล้องกับข้อความ JSON ที่กำหนด

ข้อยกเว้น

ส่งข้อยกเว้นของวากยสัมพันธ์ SyntaxError หากสตริงที่จะวิเคราะห์คำไม่ถูกต้อง JSON



2

แยกสตริง JSON ด้วยJSON.parse()และข้อมูลจะกลายเป็นวัตถุ JavaScript:

JSON.parse(jsonString)

ที่นี่ JSON แสดงถึงการประมวลผลชุดข้อมูล JSON

ลองนึกภาพเราได้รับข้อความนี้จากเว็บเซิร์ฟเวอร์:

'{ "name":"John", "age":30, "city":"New York"}'

ในการแยกวิเคราะห์เป็นวัตถุ JSON:

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}'); 

นี่objคือวัตถุ JSON ที่เกี่ยวข้องซึ่งมีลักษณะดังนี้:

{ "name":"John", "age":30, "city":"New York"}

ในการดึงค่าให้ใช้.โอเปอเรเตอร์:

obj.name // John
obj.age //30

แปลงวัตถุ JavaScript JSON.stringify()เป็นสตริงกับ


1

เพียงเพื่อแยกวิเคราะห์ปกสำหรับประเภทอินพุตที่แตกต่างกัน

แยกวิเคราะห์ข้อมูลด้วย JSON.parse () และข้อมูลจะกลายเป็นวัตถุ JavaScript

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

เมื่อใช้ JSON.parse () บน JSON ที่ได้รับมาจากอาร์เรย์วิธีการจะส่งคืนอาร์เรย์ JavaScript แทนวัตถุ JavaScript

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

ไม่อนุญาตให้ใช้วัตถุวันที่ใน JSON สำหรับวันที่ทำบางสิ่งเช่นนี้

var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';
var obj = JSON.parse(text);
obj.birth = new Date(obj.birth);

ไม่อนุญาตให้ใช้ฟังก์ชันใน JSON หากคุณต้องการรวมฟังก์ชั่นเขียนมันเป็นสตริง

var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");

0

คำถามเก่ากว่าฉันรู้ว่าไม่มีใครสังเกตเห็นวิธีแก้ปัญหานี้โดยใช้new Function()ฟังก์ชั่นไม่ระบุชื่อที่ส่งคืนข้อมูล


เป็นเพียงตัวอย่าง:

 var oData = 'test1:"This is my object",test2:"This is my object"';

 if( typeof oData !== 'object' )
  try {
   oData = (new Function('return {'+oData+'};'))();
  }
  catch(e) { oData=false; }

 if( typeof oData !== 'object' )
  { alert( 'Error in code' ); }
 else {
        alert( oData.test1 );
        alert( oData.test2 );
      }

สิ่งนี้จะปลอดภัยกว่านี้เล็กน้อยเพราะมันทำงานในฟังก์ชั่นและไม่คอมไพล์ในโค้ดของคุณโดยตรง ดังนั้นหากมีการประกาศฟังก์ชั่นภายในมันจะไม่ถูกผูกไว้กับวัตถุหน้าต่างเริ่มต้น

ฉันใช้สิ่งนี้เพื่อ 'รวบรวม' การตั้งค่าการกำหนดค่าองค์ประกอบ DOM (ตัวอย่างเช่น data data) ที่ง่ายและรวดเร็ว


0

สรุป:

Javascript (ทั้งเบราว์เซอร์และ NodeJS) มีJSONวัตถุในตัว กับวัตถุนี้มี 2 JSONวิธีที่สะดวกสำหรับการรับมือกับ พวกเขามีดังต่อไปนี้:

  1. JSON.parse() ใช้JSONเป็นอาร์กิวเมนต์ส่งคืนวัตถุ JS
  2. JSON.stringify() รับวัตถุ JS เป็นอาร์กิวเมนต์ส่งคืนJSONวัตถุ

แอปพลิเคชันอื่น ๆ :

นอกจากนี้เพื่อความสะดวกในการจัดการกับJSONพวกเขาสามารถใช้วิธีการอื่น การรวมกันของทั้งสองJSONวิธีช่วยให้เราสร้างโคลนนิ่งอาร์เรย์หรือวัตถุได้ง่ายมาก ตัวอย่างเช่น:

let arr1 = [1, 2, [3 ,4]];
let newArr = arr1.slice();

arr1[2][0] = 'changed'; 
console.log(newArr); // not a deep clone

let arr2 = [1, 2, [3 ,4]];
let newArrDeepclone = JSON.parse(JSON.stringify(arr2));

arr2[2][0] = 'changed'; 
console.log(newArrDeepclone); // A deep clone, values unchanged


0

คุณยังสามารถใช้reviverฟังก์ชั่นในการกรอง

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

JSON.parseสำหรับข้อมูลเพิ่มเติมอ่าน


0

JSON.parse เป็นวิธีที่ถูกต้องในการแปลงสตริงเป็นวัตถุ แต่ถ้าสตริงที่วิเคราะห์คำไม่ได้เป็นวัตถุหรือถ้าสตริงไม่ถูกต้องแล้วมันจะโยนข้อผิดพลาดที่จะทำให้ส่วนที่เหลือของรหัสที่จะทำลายจึงเป็น เหมาะที่จะหุ้มฟังก์ชัน JSON.parse ภายใน try-catch like like

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}

-1

ลองสิ่งนี้สิ่งนี้เขียนด้วย typescript

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }

ฉันใหม่กับ typescript สิ่งนี้จะเพิ่มประโยชน์อะไรบ้างJSON.parse()?
Marc L.

หากมีข้อยกเว้นเกิดขึ้นสิ่งนี้จะส่งคืนสตริงอินพุตของตัวเอง
Supun Dharmarathne

-1
/**
 * Safely turning a JSON string into an object
 *
 * @param {String} str - JSON String
 * @returns deserialized object, false if error
 */
export function jsonParse(str) {
  let data = null;
  try {
    data = JSON.parse(str);
  } catch (err) {
    return false;
  }
  return data;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.