Bir JSON dizesini güvenli bir şekilde bir nesneye dönüştürme


1335

Bir dizi JSON verisi verildiğinde, bu dizeyi nasıl güvenli bir şekilde bir JavaScript nesnesine dönüştürebilirim?

Açıkçası bunu güvenli olmayan bir şeyle yapabilirim:

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

ancak bu beni diğer kodları içeren JSON dizesine karşı savunmasız bırakıyor.


77
Çoğu dilde eval ek bir risk taşır. Eval, bilgisayar korsanlarının sömürülmesi için açık bir kapı bırakır. Ancak, tüm javascript istemcide çalıştığını unutmayın. Bilgisayar korsanları tarafından değiştirileceğini düşünün. Sadece konsolu kullanarak istedikleri her şeyi EVAL yapabilirler. Korumanızı sunucu tarafında oluşturmanız gerekir.
Beachhouse

19
Tamam, şimdi 2014 ve asla evalbir JSON dizesini ayrıştırmak için kullanmamalısınız çünkü kodunuzu "kod enjeksiyonuna" maruz bırakacaksınız. JSON.parse(yourString)Bunun yerine kullanın .
Daniel

JSON verileri değişmez mi?
shanechiu

@shanechiu: Eğer skaler veri türünü kastediyorsanız, evet. İçinde anahtar / değer sözdizimi olan bir dizedir.
0zkr PM

Yanıtlar:


1961

JSON.parse(jsonString) makul derecede modern bir tarayıcıyı garanti edebildiğiniz sürece saf bir JavaScript yaklaşımıdır.


74
Eminim ki Node.js için güvenlidir
Stephen

76
@vsync bunun SADECE Saf Javascript Cevabı olduğunu anlıyorsunuz ... javascript etiketinin açıklamasını okuduğunuzda bunu göreceksiniz ... " Bir çerçeve / kütüphane için bir etiket de eklenmedikçe, saf bir JavaScript cevabı bekliyordum. ".. Bunu tek javascript cevabı olduğu için +1
verdim


12
NodeJS yapıyorsanız, sadece bir JSON nesnesine bir jsonString ayrıştırmak için jQuery yüklemek hiçbir yolu yoktur. Jonathan'ın cevabını onayla
Antony

6
Göre bu bağlantı diyor rağmen, IE8 + tarafından desteklenmektedir:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

JQuery yöntemi artık kullanımdan kaldırılmıştır. Bunun yerine bu yöntemi kullanın:

let jsonObject = JSON.parse(jsonString);

Kullanımdan kaldırılmış jQuery işlevini kullanarak orijinal yanıt :

JQuery kullanıyorsanız sadece şunu kullanın:

jQuery.parseJSON( jsonString );

Tam olarak aradığınız şey (jQuery belgelerine bakın ).


7
Bu JSON.parse () üzerinden kullanmak için bir nedeni var mı?
Jon

8
jQuery.parseJSONJSON.parseVarsa varsayılan olarak kullanıldığından , bunu gerçek olanın üzerinde kullanmanın tek nedeni, <IE7 için bir yedeğe ihtiyaç duymanızdır. JQuery 1.6'da geri değiştirildi: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren

9
2016 güncellemesi: jQuery 3.0'dan itibaren, $ .parseJSON kullanımdan kaldırılmıştır ve bunun yerine yerel JSON.parse yöntemini kullanmalısınız.
jkdev

159

Bu cevap IE <7 içindir, modern tarayıcılar için yukarıdaki Jonathan'ın cevabını kontrol edin.

Bu cevap eski ve Jonathan'ın yukarıdaki cevabı ( JSON.parse(jsonString)) şimdi en iyi cevap .

JSON.org , JavaScript için dört farklı dil de dahil olmak üzere birçok dil için JSON ayrıştırıcısına sahiptir. Çoğu insan json2.js kendi goto uygulama düşünün inanıyorum .


24
Keşke insanlar bu cevabı aşağı oylamayı bırakırlar. 2008'de yayınlandığında doğruydu. Sadece yenisini oylayın.
John

22
Yanıt şimdi güncel değilse, güncellemeyi düşünün.
Sotirios Delimanolis

2
IE <8 için bunu kullanmanız gerekir.
Mahmoodvcs

74

" JSON.parse () " içindeki basit kod örneğini kullanın :

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

ve tersine çevirir:

var str = JSON.stringify(arr);

23

Bunu yapmanın diğer yolları hakkında emin değilim ama Prototip (JSON öğretici) bunu nasıl yapacağınız .

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

evalJSON()Argüman olarak true ile çağırmak gelen dizgiyi dezenfekte eder.


22

Sorun bu gibi görünüyor:

Ajax websocket vb. Yoluyla alınan ve Dize biçiminde olacak bir giriş, ancak bunun olup olmadığını bilmeniz gerekir JSON.parsable. Sorun, her zaman çalıştırırsanız JSON.parse, program "başarılı bir şekilde" devam edebilir, ancak yine de korkunç olan konsolda bir hata göreceksiniz "Error: unexpected token 'x'".

var data;

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

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

HAYIR. Sorun şu ki, bir JSON nesnesi bekliyorsunuz ve (function(){ postCookiesToHostileServer(); }());Düğüm bağlamında hatta daha az şeylerle sonuçlanabiliyorsunuz.
Yaur

Peki JSON.parse işlevlerin girişini temizler (bu durumda IIF -> nesnesi olarak yardımcı olmaz). Bu konu hakkında gitmenin en iyi yolu denemek / yakalamak. (Bkz. Düzenleme)
Cody

18

JQuery kullanıyorsanız şunları da kullanabilirsiniz:

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

Sonra gibi şeyler yapabilirsiniz

data.key1.something
data.key1.something_else

vb.


jQuery kullanıyorsunuz, değil mi?
Alexandre

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

Geri arama, JSON yapısı tarafından tanımlanan ve $.parseJSON()yöntem kullanılarak ayrıştırılan bir JavaScript nesnesi veya dizisi olacak döndürülen verilerden geçirilir .


12

Sadece eğlence için, bir işlevi kullanmanın bir yolu:

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

1
İlginç bir yaklaşım, bunu JSON.Parse ile kullanacağımdan emin değilim, ancak kutunun dışında düşünen birini görmek güzel.

5
Bu sadece evalbunu yapmak için kullanılmaya çok benzer ve güvenli değildir. : P
Florrie

7
Bu kullanımın tüm dezavantajlarına sahiptir, evalancak bakımcıların anlaması daha karmaşık ve zordur.
Quentin

9

Kullanmak JSON.parsemuhtemelen en iyi yoldur.

İşte bir canlı demo örneği .

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()Yöntemi kullanarak en kolay yolu :

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

Sonra JSON öğelerinin değerlerini alabilirsiniz, örneğin:

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

Belgelerde açıklandığı gibi jQuery kullanma jQuery.parseJSON():

JSON.parse(jsonString);

9

Yöntemi bu Data nesnesiyle kullanmayı deneyin. örn: Data='{result:true,count:1}'

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

Seri port programlama ile çalışırken bu yöntem gerçekten Nodejs'de yardımcı olur


İnsanların "eval kötüdür" için nasıl sabitlendiğini gerçekten komik ve önlemek için her şeyi yapacaklar, hatta tüm eval-işlevselliğini yeniden yazıyorlar ..
diynevala

Fikir birliği bu hile JSON nesnesine dönüştürmek güvenli bir yöntemdir? Ek js ithalatı gerekmediği için bunu kullanabilirsiniz.
Whome

1
evalVeya kullanan herhangi bir yaklaşım Functioneşit derecede savunmasız
Slai

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

5

"Daha iyi" bir yol buldum:

CoffeeScript'te:

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

Javascript'te:

var data;

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

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

4

JSON ayrıştırma her zaman bir acıdır. Giriş beklendiği gibi değilse bir hata atar ve yaptığınız işi kilitler.

Girişinizi güvenle ayrıştırmak için aşağıdaki küçük işlevi kullanabilirsiniz. Giriş geçerli olmasa veya zaten çoğu durumda daha iyi olan bir nesne olsa bile her zaman bir nesneyi döndürür:

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 olmalı
Serge K.

typeof input, null ve diziler için de nesne döndürür. Yani bunu yapmanın güvenli yolu değil.
Tahsin Turkoz

Zaten örtülü nullönce davayı ve bir dizi olan bir nesne. Test etmek istiyorsanız kullanabilirsiniz instanceof. Ayrıca, bu işlevi bir verirseniz Array, yakalayacak ve return defmükemmel ince diziyi ne zaman döndürebilir.
Serge K.

Yorumum, nesneleri yakalarken sağduyu ile ilgiliydi. İşlevim birkaç önleme sahip olabilir, ancak typeof input kullanmak nesneleri genel olarak algılamanın tercih edilen yolu değildir.
Tahsin Turkoz

IMO, sağduyu, toString()bir değişkenin nesne olup olmadığını kontrol etmek için yöntem kullanmaz . Bkz angularjs , jQuery , Underscore , hatta Devs
Serge K.


3

Eğer böyle bir dizemiz varsa:

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

JSON.parsebu dizeyi bir JSON nesnesine dönüştürmek için iki kez kullanabiliriz :

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

JSON nesnesinden değerleri kullanarak şunları elde edebiliriz:

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

Sonuç:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() işleve iletilen tüm JSON dizelerini bir JSON nesnesine dönüştürür.

Daha iyi anlamak için, F12tarayıcınızda "Elemanı Denetle" yi açmak için düğmesine basın ve aşağıdaki komutları yazmak için konsola gidin:

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

Şimdi komutu çalıştırın:

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

Nesne olarak çıktı alırsınız {result: true, count: 1}.

Bu Object'i kullanmak için, değişkeni atayabilirsiniz, belki obj:

var obj = JSON.parse(response);

Ve objdot ( .) operatörünü kullanarak JSON nesnesinin özelliklerine erişebilirsiniz.

Komutu çalıştırmayı deneyin:

console.log(obj.result);

3

Resmi belgeler :

JSON.parse()Yöntem, bir JSON String, String tarafından tarif edilen bir JavaScript değeri veya nesne oluşturmak ayrıştırır. reviverElde edilen nesne döndürülmeden önce dönüşüm gerçekleştirmek için isteğe bağlı bir işlev sağlanabilir.

Sözdizimi:

JSON.parse(text[, reviver])

Parametreler:

text : JSON olarak ayrıştırılacak dize. JSON sözdiziminin açıklaması için JSON nesnesine bakın.

reviver (optional) : Bir işlev varsa, bu, ayrıştırma ile başlangıçta üretilen değerin döndürülmeden önce nasıl dönüştürüldüğünü belirler.

Geri dönüş değeri

Verilen JSON metnine karşılık gelen nesne.

İstisnalar

Ayrıştırılacak dize geçerli JSON değilse, bir SyntaxError istisnası atar.



2

JSON dizesini ile ayrıştırdığınızda JSON.parse()veriler bir JavaScript nesnesi haline gelir:

JSON.parse(jsonString)

Burada, JSON, JSON veri kümesini işlemeyi temsil eder.

Bu metni bir web sunucusundan aldığımızı düşünün:

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

Bir JSON nesnesine ayrıştırmak için:

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

İşte objbenziyor ilgili JSON nesnesidir:

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

Bir değer getirmek için .işleci kullanın :

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

Bir JavaScript nesnesini ile bir dizeye dönüştürün JSON.stringify().


1

Farklı giriş türleri için sadece kapak ayrıştırma işlemine

Verileri JSON.parse () ile ayrıştırdığınızda veriler bir JavaScript nesnesi haline gelir.

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

Bir diziden türetilen bir JSON üzerinde JSON.parse () kullanılırken, yöntem bir JavaScript nesnesi yerine bir JavaScript dizisi döndürür.

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

JSON'da tarih nesnelerine izin verilmez. Tarihler böyle bir şey yapın

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

JSON'da işlevlere izin verilmez. Bir işlev eklemeniz gerekirse, dize olarak yazın.

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

0

Eski soru, biliyorum, ancak kimse bu çözümü kullanarak fark new Function()etmez, verileri döndüren anonim bir işlev.


Sadece bir örnek:

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

Bu biraz daha güvenlidir, çünkü bir fonksiyonun içinde çalışır ve kodunuzda doğrudan derlemez. Dolayısıyla, içinde bir işlev bildirimi varsa, varsayılan pencere nesnesine bağlı olmayacaktır.

Bunu DOM öğelerinin (örneğin veri özniteliği) yapılandırma ayarlarını basit ve hızlı 'derlemek' için kullanın.


0

Özet:

Javascript (hem tarayıcı hem de NodeJS) yerleşik bir JSONnesneye sahiptir. Bu nesne üzerinde başa çıkmak için 2 uygun yöntem vardır JSON. Bunlar:

  1. JSON.parse() Bağımsız JSONdeğişken olarak alır, JS nesnesini döndürür
  2. JSON.stringify() Bağımsız değişken JSONnesneyi döndürdüğü için JS nesnesini alır

Diğer uygulamalar:

Ayrıca çok rahat bir şekilde uğraşmak JSONiçin başka araçlar için kullanılabilirler. Her iki JSONyöntemin kombinasyonu, dizilerin veya nesnelerin derin klonlarını yapmamızı sağlar. Örneğin:

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

reviverFiltrelemek için işlevi de kullanabilirsiniz .

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

Daha fazla bilgi için okuyun JSON.parse.


0

JSON.parse, bir dizeyi bir nesneye dönüştürmenin doğru yoludur, ancak ayrıştırılan dize nesne değilse veya dize doğru değilse, kodun geri kalanının bozulmasına neden olacak bir hata atar. gibi try-catch içine JSON.parse işlevi sarmak için ideal

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

-1

Bunu deneyin.Bu bir daktilo ile yazılmış.

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

Typescript'te yeniyim. Bu ne fayda sağlıyor JSON.parse()?
Marc

Herhangi bir istisna oluşursa, bu girdi dizesinin kendisini döndürür
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;
}
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.