Nesne dizesini JSON'a dönüştürme


165

Bir nesneyi açıklayan bir dizeyi JavaScript (veya jQuery) kullanarak bir JSON dizesine nasıl dönüştürebilirim?

örneğin: Bunu dönüştür ( geçerli bir JSON dizesi DEĞİL ):

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"

bunun içine:

str = '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

eval()Mümkünse kullanmaktan kaçınmak isterim .


Dizeniz neden ilk başta geçerli JSON değil? Bunu nasıl üretiyorsun?
Rocket Hazmat

2
Dize, şöyle bir data-attrubute içinde saklanır : <div data-object="{hello:'world'}"></div>ve HTML'de tek tırnak kullanmak istemiyorum (bu yüzden muhtemelen güvenilmez)
snorpey

5
@snorpey: <div data-object='{"hello":"world"}'></div>% 100 geçerli HTML'dir (tek tırnakların ona güvenmekle ne ilgisi vardır?). Bu şekilde yaparsanız, sadece yapabilirsiniz JSON.parseve iyi çalışır. Not: anahtarların da alıntılanması gerekir.
Rocket Hazmat

@ Roket çabalarınız için teşekkürler! Sadece HTML'de tek tırnak kullanmak zorunda kalmanın bir yolunu bulmak istedim (% 100 geçerli olmasına rağmen) ve JSON gösterimi.
snorpey

@snorpey: Yollarda JSON'u ilk etapta bir HTML özelliğine koymak değil. Sanırım çift ​​tırnak kullanabilirsiniz ve JSON olanlar kaçmak olabilir<div data-object="{\"hello\":\"world\"}"></div> . Özellikte geçerli JSON kullanmak istemiyorsanız, kendi biçiminizi oluşturmanız ve kendiniz ayrıştırmanız gerekir.
Rocket Hazmat

Yanıtlar:


181

Dize güvenilir bir kaynaktan geliyorsa şunu kullanabilirsiniz evalardından JSON.stringifysonucu. Bunun gibi:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

Unutmayın ki eval bir nesne değişmezi, bu parantez içinde sarılı zorundadır aksi ayraçları bir blok yerine bir nesne olarak çözümlenir.

Ayrıca, sadece geçerli JSON'da nesneyi kodlamak ve başlamak, kodlamak, sonra muhtemelen tekrar ayrıştırmak zorunda kalmamak için geçerli JSON'da kodlamanın çok daha iyi olacağı sorusundaki yorumlara katılıyorum . HTML tek tırnaklı nitelikleri destekler (dizelerin içindeki tırnak işaretlerini HTML olarak kodladığınızdan emin olun).


Bu mantıklı değil, eğer dize güvenilir kaynaktan geliyorsa, neden onu dönüştürüyoruz?
allenhwkim

2
@allenhwkim Fikir geçersiz JSON'dan geçerli JSON'a dönüştürmektir, bu nedenle evaldizeyi bir JavaScript nesnesine dönüştürür (dize, geçerli JSON olmasa bile geçerli JavaScript'i temsil ettiği sürece çalışır). Daha sonra JSON.stringifybir nesneden (geçerli) bir JSON dizesine dönüşür. evalDize güvenilir bir kaynaktan değilse, arama yapmak tehlikelidir, çünkü siteler arası komut dosyası saldırıları olasılığını açan herhangi bir JavaScript'i çalıştırabilir.
Matthew Crumley

2
Örneğin, dize şu şekilde oluşturulmuşsa eval bu durumda yine de kötü şeyler yapar: var str = "(function () {console.log (\" bad \ ")}) ()";
Rondo

Eval () kullanıldığında JS kodu yürütülür. Kolayca istismar edilebilir.
FisNaN

@allenhwkim: Hiçbir kaynağa asla güvenmiyoruz. BT'ye güven, kontrol, kontrol ve tekrar kontrol anlamına gelir.
Laszlo Varga

110

Dizeniz geçerli JSON değil, bu nedenle JSON.parse(veya jQuery $.parseJSON) çalışmaz.

Bunun bir yolu eval, "geçersiz" JSON'u "ayrıştırmak" ve ardından stringifygeçerli JSON'a "dönüştürmek" için kullanmaktır.

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
str = JSON.stringify(eval('('+str+')'));

Ben geçersiz JSON "düzeltmek" denemek yerine, öncelikle geçerli JSON ile başlar öneririz. Nasıl strüretiliyorsa, oluşturulmadan önce, sonra değil, orada sabitlenmelidir.

EDIT : Bu dizenin bir veri özniteliğinde saklandığını (yorumlarda) söylediniz:

<div data-object="{hello:'world'}"></div>

Burada düzeltmenizi öneririm, bu yüzden sadece JSON.parsed olabilir. İlk olarak, hem anahtarların hem de değerlerin çift tırnak içine alınması gerekir. Şöyle görünmelidir (HTML'deki tek tırnak içine alınan özellikler geçerlidir):

<div data-object='{"hello":"world"}'></div>

Şimdi, JSON.parse(veya jQuery $.parseJSON) kullanabilirsiniz.

var str = '{"hello":"world"}';
var obj = JSON.parse(str);

49

jQuery.parseJSON

str = jQuery.parseJSON(str)

Düzenle. Geçerli bir JSON dizeniz olması şartıyla


1
Doğru JSON dizesini nesneye nasıl dönüştüreceğim sorusunu gördüm
Farmor

43

Aşağıdaki bağlantıda basit kod kullanın:

http://msdn.microsoft.com/es-es/library/ie/cc836466%28v=vs.94%29.aspx

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

ve ters

var str = JSON.stringify(arr);

Jsontext'i yeni String (jsontext) aracılığıyla bir String nesnesine dönüştürmek, tür güvenliği için muhtemelen daha da iyidir.
Bulanık Analiz

@fuzzyanalysis: Hayır, ilkel ambalajlar asla kullanılmamalıdır.
Ry-

1
@LouiseMcMahon tarafından belirtilen JSON.parse () burada kabul edilen cevap olmalıdır
pixel 67

24

Umarım bu küçük işlev geçersiz JSON dizesini geçerli olana dönüştürür.

function JSONize(str) {
  return str
    // wrap keys without quote with valid double quote
    .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":'})    
    // replacing single quote wrapped ones to double quote 
    .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"'})         
}

Sonuç

var invalidJSON = "{ hello: 'world',foo:1,  bar  : '2', foo1: 1, _bar : 2, $2: 3, 'xxx': 5, \"fuz\": 4, places: ['Africa', 'America', 'Asia', 'Australia'] }"
JSON.parse(invalidJSON) 
//Result: Uncaught SyntaxError: Unexpected token h VM1058:2
JSON.parse(JSONize(invalidJSON)) 
//Result: Object {hello: "world", foo: 1, bar: "2", foo1: 1, _bar: 2…}

JSON'u kullanarak b'nin değerini kaldırmaya çalışıyoruz. Kodumuzu inceleyin ve bu iyi bir çözüm gibi görünüyor. Hala sürekli değiştirmeyi elle ele almamız gerekecek, ancak en azından bu, bu davaları içermeye izin veriyor.
ravemir

1
Neredeyse mükemmel. : Değerlerden birinde olduğunda çalışmaz .
seler

9

Dikkatli kullanın (çünkü eval()):

function strToJson(str) {
  eval("var x = " + str + ";");
  return JSON.stringify(x);
}

şu şekilde arayın:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );

3
İsimsiz aşağı seçmene. Size daha iyi bir çözüm sunmaya davet ediyorum. Bunun dışında aşağı oylamanın bir nedeni iyi olurdu.
Ocak'ta Tomalak

1
@Rocket: Yanılıyorsun. a) eval()Bunu yapmanın tek yolu. b) OP'yi bu konuda uyardım. c) Matthew Crumley'in cevabına bakın ve daha iyi bir açıklama düşünün. (Oh, ve d) ifade eval()kötüdür bu genelleştirilmiş biçim saçmalıktır.)
Tomalak

2
@Rocket: Ah, tam burada yanlış anlaşılma. Maalesef, aşağı oylamanın size ait olduğunu düşündüm. :)
Tomalak

1
@kuboslav: İyi çalışıyor, test ettin mi? eval("var x = " + str + ";")Tamamen geçerli bir JS yapıyor . Yapmanıza gerek yok var x = ({a:12}).
Rocket Hazmat

2
@kuboslav IE7'nin yerel JSON desteği olmadığından IE7'de çalışmaz. Kullandığınız anda çalışmaya başlayacaktır json2.js. Tetikleyici mutlu olmayın.
Tomalak

4

Feragatname: bunu evde denemeyin veya diğer geliştiricilerin sizi ciddiye almasını gerektiren herhangi bir şey için:

JSON.stringify(eval('(' + str + ')'));

Orada yaptım.
Tho yapmamaya çalışın, eval sizin için KÖTÜ. Yukarıda belirtildiği gibi, eski tarayıcılar (IE7 ve altı) için Crockford'un JSON şemasını kullanın

Bu yöntem, dizenizin geçerli bir javascript olmasını gerektirir ; bu, daha sonra JSON'a serileştirilebilen bir javascript nesnesine dönüştürülür.

düzenleme: Roket önerilen olarak düzeltildi.


Öyle olmalı JSON.stringify(eval('('+str+')'));, ben kondom değil eval, ama onun dize geçerli JSON JSON.parsedeğil yani çalışmıyor.
Rocket Hazmat

4

Bu eski konu ile ilgilenen biri için cevabımı verdim.

Yanlış biçimlendirilmiş bir JSON dizesini kullanmadan bir JavaScript nesnesine dönüştüren jQuery eklentisi ve demo için HTML5 data- * ayrıştırıcısını oluşturdum .eval()

Aşağıdaki HTML5 data- * özelliklerini geçebilir:

<div data-object='{"hello":"world"}'></div>
<div data-object="{hello:'world'}"></div>
<div data-object="hello:world"></div>

nesneye:

{
    hello: "world"
}


2

Bu başarıyı gerçekleştirmenin çok daha basit bir yolu var, sadece bir dize öğesinin JavaScript nesnesi olarak geri dönmesini zorlamak için bir kukla öğenin onclick niteliğini ele geçirin:

var jsonify = (function(div){
  return function(json){
    div.setAttribute('onclick', 'this.__json__ = ' + json);
    div.click();
    return div.__json__;
  }
})(document.createElement('div'));

// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)

İşte bir demo: http://codepen.io/csuwldcat/pen/dfzsu (konsolunuzu açın)


2

Sonuç için "eval" sonra JSON.stringify sonra JSON.parse kullanmanız gerekir.

 var errorString= "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
 var jsonValidString = JSON.stringify(eval("(" + errorString+ ")"));
 var JSONObj=JSON.parse(jsonValidString);

resim açıklamasını buraya girin


1

Yuvarlak köşeli parantezler yazmalısınız, çünkü bunlar olmadan evalkıvrımlı parantez içindeki kodu komut bloğu olarak kabul eder.

var i = eval("({ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] })");

1

En iyi ve en güvenli bahsiniz JSON5 - JSON for Humans olacaktır . Bu kullanım durumu için özel olarak yaratılmıştır.

const result = JSON5.parse("{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }");

console.log(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/json5/0.5.1/json5.min.js"></script>


1

Yeni Function () kullanmak, eval'den daha iyidir, ancak yine de sadece güvenli girdi ile kullanılmalıdır.

const parseJSON = obj => Function('"use strict";return (' + obj + ')')();

console.log(parseJSON("{a:(4-1), b:function(){}, c:new Date()}"))
// outputs: Object { a: 3, b: b(), c: Date 2019-06-05T09:55:11.777Z }

Kaynaklar: MDN , 2 kalite


0

Yukarıdaki basit örneğiniz için, bunu 2 basit normal ifade yerine kullanarak yapabilirsiniz:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
 => '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

Büyük uyarı : Bu saf yaklaşım, nesnenin bir 'veya :karakter içeren dizeleri olmadığını varsayar . Örneğin, kullanmadan aşağıdaki nesne dizesini JSON dönüştürmek için iyi bir yol düşünemiyorum eval:

"{ hello: 'world', places: [\"America: The Progressive's Nightmare\"] }"

0

Sadece tuhaflıkları için, dizenizi babel-standalone

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";

function toJSON() {
  return {
    visitor: {
      Identifier(path) {
        path.node.name = '"' + path.node.name + '"'
      },
      StringLiteral(path) {
        delete path.node.extra
      }
    }
  }
}
Babel.registerPlugin('toJSON', toJSON);
var parsed = Babel.transform('(' + str + ')', {
  plugins: ['toJSON']
});
var json = parsed.code.slice(1, -2)
console.log(JSON.parse(json))
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>


0

var str = "{merhaba: 'dünya', yerler: ['Afrika', 'Amerika', 'Asya', 'Avustralya']}" var fStr = str .replace (/ ([Az] *) (:) / g, '"$ 1":'). değiştirin (/ '/ g, "\" ")

console.log (JSON.parse (fStr))resim açıklamasını buraya girin

Üzgünüm, telefonumdayım, işte bir resim.


0

Eval kullanmadan bir regex ile bir çözüm:

str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")

Bu tek satır 'dize' çift tırnak "dize" ile değiştirilen tüm olası oluşumları (/ g bayrağı) için çalışması gerektiğini düşünüyorum.


0
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

-1

Belki bunu denemek zorundasınız:

str = jQuery.parseJSON(str)

Soru "veya jQuery" belirtildi ve eğer mevcutsa bu mükemmel bir çözümdür.
Ecropolis
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.