Biến một cách an toàn một chuỗi JSON thành một đối tượng


1336

Đưa ra một chuỗi dữ liệu JSON, làm cách nào tôi có thể biến chuỗi đó thành đối tượng JavaScript một cách an toàn?

Rõ ràng tôi có thể làm điều này một cách không an toàn với một cái gì đó như:

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

nhưng điều đó khiến tôi dễ bị tổn thương bởi chuỗi JSON chứa mã khác, điều này có vẻ rất nguy hiểm khi chỉ đơn giản là eval.


77
Trong hầu hết các ngôn ngữ, eval mang một rủi ro bổ sung. Eval để lại một cánh cửa mở để bị tin tặc khai thác. TUY NHIÊN, hãy nhớ rằng tất cả các javascript chạy trên máy khách. MỞ RỘNG rằng nó sẽ được thay đổi bởi tin tặc. Họ có thể ĐÁNH GIÁ bất cứ điều gì họ muốn, chỉ bằng cách sử dụng bàn điều khiển. Bạn phải xây dựng sự bảo vệ của bạn ở phía máy chủ.
Beachhouse

19
Ok, bây giờ là năm 2014 và bạn không bao giờ nên sử dụng evalđể phân tích chuỗi JSON vì bạn sẽ hiển thị mã của mình thành "mã tiêm". Sử dụng JSON.parse(yourString)thay thế.
Daniel

Dữ liệu JSON có phải là chữ không?
shanechiu

@shanechiu: nếu bạn có nghĩa là một kiểu dữ liệu vô hướng, đúng vậy. Chỉ là một chuỗi có cú pháp khóa-giá trị trong đó.
0zkr PM

Câu trả lời:


1962

JSON.parse(jsonString) là một cách tiếp cận JavaScript thuần túy miễn là bạn có thể đảm bảo một trình duyệt hợp lý hiện đại.


74
Tôi khá chắc chắn rằng nó an toàn cho Node.js
Stephen

76
@vsync Bạn nhận ra rằng đây là CHỈ tinh khiết Javascript trả lời ... nếu bạn đọc các mô tả cho thẻ javascript bạn sẽ thấy điều này ... " Trừ một thẻ cho một khuôn khổ / thư viện cũng được bao gồm, một câu trả lời Javascript tinh khiết là mong đợi. ".. Tôi cho điểm này là +1 vì là câu trả lời javascript duy nhất ...
iConnor 21/07/13


12
Nếu bạn đang làm NodeJS, không có cách nào tôi tải lên jQuery chỉ để phân tích jsonString thành một đối tượng JSON. Vì vậy, hãy đưa ra câu trả lời của Jonathan
Antony

6
Theo liên kết này, nó được hỗ trợ bởi IE8 +, mặc dù nó nói:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

Phương thức jQuery hiện không được chấp nhận. Sử dụng phương pháp này thay thế:

let jsonObject = JSON.parse(jsonString);

Câu trả lời gốc sử dụng chức năng jQuery không dùng nữa :

Nếu bạn đang sử dụng jQuery, chỉ cần sử dụng:

jQuery.parseJSON( jsonString );

Đó chính xác là những gì bạn đang tìm kiếm (xem tài liệu jQuery ).


7
Có lý do để sử dụng điều này trên JSON.parse () không?
Jon

8
jQuery.parseJSONmặc định sử dụng JSON.parsenếu nó tồn tại, vì vậy lý do duy nhất để sử dụng cái này so với thực tế là nếu bạn cần một dự phòng cho <IE7. Nó đã được thay đổi cách trở lại trong jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren

9
Cập nhật năm 2016: Kể từ jQuery 3.0, $ .parseJSON không được dùng nữa và bạn nên sử dụng phương thức JSON.parse gốc thay thế.
jkdev

159

Câu trả lời này dành cho IE <7, đối với các trình duyệt hiện đại, hãy kiểm tra câu trả lời của Jonathan ở trên.

Câu trả lời này đã lỗi thời và câu trả lời của Jonathan ở trên ( JSON.parse(jsonString)) hiện là câu trả lời tốt nhất .

JSON.org có các trình phân tích cú pháp JSON cho nhiều ngôn ngữ, bao gồm bốn ngôn ngữ khác nhau cho JavaScript. Tôi tin rằng hầu hết mọi người sẽ xem xét việc thực hiện goto của json2.js .


24
Tôi ước mọi người sẽ ngừng bỏ phiếu - câu trả lời này. Nó là chính xác khi nó được đăng vào năm 2008. Chỉ cần nâng cấp cái mới.
Giăng

22
Nếu câu trả lời đã lỗi thời, hãy xem xét cập nhật nó.
Sotirios Delimanolis 7/03/2015

2
đối với IE <8 bạn cần sử dụng cái này.
Mahmoodvcs 16/07/2015

74

Sử dụng ví dụ mã đơn giản trong " JSON.parse () ":

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

và đảo ngược nó:

var str = JSON.stringify(arr);

23

Tôi không chắc chắn về các cách khác để làm điều đó nhưng đây là cách bạn thực hiện trong Prototype (hướng dẫn JSON) .

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

Gọi evalJSON()với đúng như đối số vệ sinh chuỗi đến.


22

Đây dường như là vấn đề:

Một đầu vào được nhận thông qua Ajax websocket, v.v. và nó sẽ ở định dạng Chuỗi, nhưng bạn cần biết nếu có JSON.parsable. Vấn đề là, nếu bạn luôn chạy nó JSON.parse, chương trình CÓ THỂ tiếp tục "thành công" nhưng bạn vẫn sẽ thấy một lỗi được ném trong bảng điều khiển với sự sợ hãi "Error: unexpected token 'x'".

var data;

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

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

KHÔNG. Vấn đề là bạn đang mong đợi một đối tượng JSON và có thể kết thúc bằng (function(){ postCookiesToHostileServer(); }());hoặc thậm chí những thứ khó hiểu hơn trong bối cảnh của Node.
Yaur

Vâng JSON.parse sẽ loại bỏ đầu vào của các hàm (trong trường hợp này sẽ không giúp ích gì cho đối tượng IIF -> của nó). Có vẻ như cách tốt nhất để đi về chủ đề này là thử / bắt. (Xem chỉnh sửa)
Cody

18

Nếu bạn đang sử dụng jQuery , bạn cũng có thể sử dụng:

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

Sau đó, bạn có thể làm những việc như

data.key1.something
data.key1.something_else

Vân vân.


bạn đang sử dụng jQuery phải không?
Alexandre C.

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

Cuộc gọi lại được truyền dữ liệu trả về, đây sẽ là một đối tượng hoặc mảng JavaScript như được định nghĩa bởi cấu trúc JSON và được phân tích cú pháp bằng $.parseJSON()phương thức.


12

Để giải trí, đây là cách sử dụng chức năng:

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

1
Cách tiếp cận thú vị, tôi không chắc chắn tôi sẽ sử dụng điều này với JSON.Pude có sẵn, nhưng thật tuyệt khi thấy ai đó nghĩ bên ngoài hộp.

5
Điều này rất giống với việc chỉ sử dụng evalđể làm điều đó và không an toàn. : P
Florrie

7
Điều này có tất cả các nhược điểm của việc sử dụng evalnhưng phức tạp hơn và khó hiểu hơn cho người bảo trì.
Quentin

9

Sử dụng JSON.parsecó lẽ là cách tốt nhất.

Đây là một ví dụ demo trực tiếp .

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

Cách dễ nhất để sử dụng parse()phương pháp:

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

Sau đó, bạn có thể lấy các giá trị của các phần tử JSON, ví dụ:

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

Sử dụng jQuery như được mô tả trong jQuery.parseJSON()tài liệu:

JSON.parse(jsonString);

9

Hãy thử sử dụng phương thức với đối tượng Dữ liệu này. ví dụ: Data='{result:true,count:1}'

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

Phương pháp này thực sự hữu ích trong Nodejs khi bạn đang làm việc với lập trình cổng nối tiếp


Thật là buồn cười khi mọi người bị gắn vào "eval is evil" và họ sẽ làm mọi cách để tránh nó, thậm chí viết lại toàn bộ chức năng eval ..
diynevala

Có phải sự đồng thuận thủ thuật này là một phương thức an toàn biến chuỗi thành đối tượng JSON? Tôi có thể sử dụng điều này vì không cần nhập thêm js.
Ai

1
MỌI phương pháp sử dụng evalhoặc Functiondễ bị tổn thương như nhau
Slai

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

5

Tôi tìm thấy một cách "tốt hơn":

Trong CoffeeScript:

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

Trong Javascript:

var data;

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

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

4

Phân tích cú pháp JSON luôn là một nỗi đau. Nếu đầu vào không như mong đợi, nó sẽ báo lỗi và làm hỏng những gì bạn đang làm.

Bạn có thể sử dụng chức năng nhỏ sau đây để phân tích cú pháp đầu vào của bạn một cách an toàn. Nó luôn biến một đối tượng ngay cả khi đầu vào không hợp lệ hoặc đã là một đối tượng tốt hơn cho hầu hết các trường hợp:

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]'nên là typeof input === 'object'IMO
Serge K.

Kiểu đầu vào trả về đối tượng cho null và mảng là tốt. Vì vậy, nó không phải là cách an toàn để làm điều này.
Tahsin Turkoz

Bạn đã bao gồm nulltrường hợp trước đó và một mảng một Đối tượng. Nếu bạn muốn kiểm tra nó, bạn có thể sử dụng instanceof. Hơn nữa, nếu bạn cung cấp cho hàm này một hàm Array, nó sẽ bắt và return defkhi nào nó có thể trả về mảng hoàn toàn tốt.
Serge K.

Nhận xét của tôi là về một ý thức chung trong khi bắt các đối tượng. Hàm của tôi có thể có một số cách ngăn chặn nhưng sử dụng kiểu nhập liệu không phải là cách ưa thích để phát hiện các đối tượng nói chung.
Tahsin Turkoz

IMO, thông thường không sử dụng toString()phương pháp để kiểm tra xem biến có phải là một đối tượng hay không. Xem AngularJS , jQuery , Underscore hoặc thậm chí các nhà phát triển
Serge K.


3

Nếu chúng ta có một chuỗi như thế này:

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

sau đó chúng ta chỉ cần sử dụng JSON.parsehai lần để chuyển đổi chuỗi này thành đối tượng JSON:

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

Và chúng ta có thể trích xuất các giá trị từ đối tượng JSON bằng cách sử dụng:

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

Kết quả sẽ là:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() chuyển đổi bất kỳ chuỗi JSON nào được truyền vào hàm thành một đối tượng JSON.

Để hiểu rõ hơn, nhấn F12để mở "Kiểm tra phần tử" trong trình duyệt của bạn và đi đến bảng điều khiển để viết các lệnh sau:

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

Bây giờ hãy chạy lệnh:

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

Bạn sẽ nhận được đầu ra dưới dạng Object {result: true, count: 1} .

Để sử dụng Đối tượng đó, bạn có thể gán nó cho biến, có thể obj:

var obj = JSON.parse(response);

Bằng cách sử dụng objvà dấu chấm (. toán tử ), bạn có thể truy cập các thuộc tính của đối tượng JSON.

Hãy thử chạy lệnh:

console.log(obj.result);

3

Tài liệu chính thức :

Các JSON.parse()phương pháp phân tích một chuỗi JSON, xây dựng giá trị JavaScript hoặc đối tượng được mô tả bởi chuỗi. Một tùy chọnreviver chức năng có thể được cung cấp để thực hiện chuyển đổi trên đối tượng kết quả trước khi nó được trả về.

Cú pháp:

JSON.parse(text[, reviver])

Thông số:

text : Chuỗi phân tích cú pháp dưới dạng JSON. Xem đối tượng JSON để biết mô tả về cú pháp JSON.

reviver (optional) : Nếu một hàm, điều này quy định cách giá trị ban đầu được tạo ra bằng cách phân tích cú pháp được chuyển đổi, trước khi được trả về.

Giá trị trả về

Đối tượng tương ứng với văn bản JSON đã cho.

Ngoại lệ

Ném một ngoại lệ SyntaxError nếu chuỗi phân tích cú pháp không phải là JSON hợp lệ.


2

Chuyển đổi đối tượng thành JSON và sau đó phân tích cú pháp nó, hoạt động với tôi, như:

JSON.parse(JSON.stringify(object))

1
Bạn đã bỏ lỡ một khung đóng cửa.
Salomon Zhang

2

Phân tích chuỗi JSON JSON.parse()và dữ liệu trở thành đối tượng JavaScript:

JSON.parse(jsonString)

Ở đây, JSON đại diện để xử lý bộ dữ liệu JSON.

Hãy tưởng tượng chúng tôi đã nhận được văn bản này từ một máy chủ web:

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

Để phân tích thành một đối tượng JSON:

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

Đây objlà đối tượng JSON tương ứng trông như sau:

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

Để tìm nạp một giá trị, sử dụng .toán tử:

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

Chuyển đổi một đối tượng JavaScript thành một chuỗi với JSON.stringify().


1

Chỉ cần phân tích cú pháp cho các loại đầu vào khác nhau

Phân tích dữ liệu bằng JSON.parse () và dữ liệu trở thành đối tượng JavaScript.

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

Khi sử dụng JSON.parse () trên JSON xuất phát từ một mảng, phương thức sẽ trả về một mảng JavaScript, thay vì một đối tượng JavaScript.

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

Các đối tượng ngày không được phép trong JSON. Đối với những ngày làm điều gì đó như thế này

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

Các hàm không được phép trong JSON. Nếu bạn cần bao gồm một hàm, hãy viết nó dưới dạng một chuỗi.

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

0

Câu hỏi cũ hơn, tôi biết, tuy nhiên không ai chú ý đến giải pháp này bằng cách sử dụng new Function()một hàm ẩn danh trả về dữ liệu.


Chỉ là một ví dụ:

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

Điều này an toàn hơn một chút vì nó thực thi bên trong một hàm và không biên dịch trực tiếp mã của bạn. Vì vậy, nếu có một khai báo hàm bên trong nó, nó sẽ không bị ràng buộc với đối tượng cửa sổ mặc định.

Tôi sử dụng điều này để 'biên dịch' cài đặt cấu hình của các thành phần DOM (ví dụ: thuộc tính dữ liệu) đơn giản và nhanh chóng.


0

Tóm lược:

Javascript (cả trình duyệt và NodeJS) đều có JSONđối tượng tích hợp. Trên đối tượng này có 2 phương thức thuận tiện để xử lý JSON. Họ là như sau:

  1. JSON.parse() Lấy JSONlàm đối số, trả về đối tượng JS
  2. JSON.stringify() Đưa đối tượng JS làm đối số trả về JSONđối tượng

Các ứng dụng khác:

Bên cạnh đó để đối phó rất thuận tiện với JSONhọ có thể được sử dụng cho các phương tiện khác. Sự kết hợp của cả hai JSONphương pháp cho phép chúng ta thực hiện rất dễ dàng tạo các bản sao sâu của mảng hoặc đối tượng. Ví dụ:

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

Bạn cũng có thể sử dụng reviverchức năng để lọc.

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

Để biết thêm thông tin đọc JSON.parse.


0

JSON.parse là cách đúng để chuyển đổi một chuỗi thành một đối tượng nhưng nếu chuỗi được phân tích cú pháp không phải là đối tượng hoặc nếu chuỗi không đúng thì nó sẽ gây ra lỗi khiến phần còn lại của mã bị phá vỡ. lý tưởng để bọc hàm JSON.parse bên trong try-Catch như

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

-1

Hãy thử cái này. Cái này được viết bằng bản thảo.

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

Tôi chưa quen với Bản đánh máy. Điều này mang lại lợi ích JSON.parse()gì?
Marc L.

Nếu có bất kỳ ngoại lệ nào xảy ra, điều này sẽ trả về chính chuỗi đầu vào
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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.