Konversi objek string ke JSON

165

Bagaimana saya bisa mengkonversi string yang menggambarkan objek menjadi string JSON menggunakan JavaScript (atau jQuery)?

mis: Konversi ini ( BUKAN string JSON yang valid):

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

dalam hal ini:

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

Saya ingin menghindari penggunaan eval()jika memungkinkan.

Snorpey
sumber
Mengapa string Anda tidak valid JSON di tempat pertama? Bagaimana Anda menghasilkan itu?
Rocket Hazmat
2
String disimpan dalam data-attrubute, seperti ini: <div data-object="{hello:'world'}"></div>dan saya tidak ingin menggunakan tanda kutip tunggal dalam HTML (jadi mungkin tidak dapat dipercaya)
snorpey
5
@snorpey: <div data-object='{"hello":"world"}'></div>apakah HTML yang valid 100% (apa hubungannya dengan tanda kutip dengan percaya atau tidak?). Jika Anda melakukannya dengan cara ini, Anda bisa JSON.parsemelakukannya dan itu akan berfungsi dengan baik. Catatan: kunci juga perlu dikutip.
Rocket Hazmat
@ Roket terima kasih atas upaya Anda! Saya hanya ingin menemukan cara untuk menggunakan tanda kutip tunggal dalam HTML (meskipun 100% valid) dan notasi JSON.
Snorpey
@snorpey: Mereka berpaling bukan untuk menempatkan JSON di atribut HTML di tempat pertama. Saya kira Anda bisa menggunakan tanda kutip ganda, dan lolos dari yang ada di JSON <div data-object="{\"hello\":\"world\"}"></div>. Jika Anda tidak ingin menggunakan JSON yang valid dalam atribut, maka Anda harus membuat format sendiri dan menguraikannya sendiri.
Rocket Hazmat

Jawaban:

181

Jika string adalah dari sumber yang terpercaya , Anda bisa menggunakan evalkemudian JSON.stringifyhasilnya. Seperti ini:

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

Perhatikan bahwa ketika Anda evalsebuah objek literal, itu harus dibungkus dengan tanda kurung, jika tidak, kawat gigi diurai sebagai blok, bukan objek.

Saya juga setuju dengan komentar di bawah pertanyaan bahwa akan jauh lebih baik untuk hanya menyandikan objek di JSON yang valid untuk memulai dan menghindari harus menguraikan, menyandikan, kemudian mungkin menguraikannya lagi . HTML mendukung atribut yang dikutip tunggal (pastikan untuk menyandikan HTML setiap tanda kutip tunggal di dalam string).

Matthew Crumley
sumber
ini tidak masuk akal, jika string berasal dari sumber tepercaya, mengapa kita mengubahnya sebagai gantinya kita menjadikannya json yang valid.
allenhwkim
2
@allenhwkim Idenya adalah untuk mengkonversi dari JSON yang tidak valid ke JSON yang valid, jadi evalkonversikan string ke objek JavaScript (yang berfungsi, selama string tersebut merepresentasikan JavaScript yang valid, walaupun itu bukan JSON yang valid). Kemudian JSON.stringifymengonversi dari objek kembali ke string JSON (valid). Memanggil evalberbahaya jika string bukan dari sumber tepercaya karena itu benar-benar dapat menjalankan JavaScript yang membuka kemungkinan serangan skrip lintas situs.
Matthew Crumley
2
eval masih akan melakukan hal-hal buruk dalam hal ini jika string dibangun, misalnya, seperti ini: var str = "(function () {console.log (\" bad \ ")}) ()";
Rondo
Menggunakan eval () akan mengeksekusi kode JS. Itu bisa dengan mudah disalahgunakan.
FisNaN
@allenhwkim: kami tidak pernah mempercayai sumber apa pun. Percaya pada IT berarti memeriksa, memeriksa, dan memeriksa lagi.
Laszlo Varga
110

String Anda bukan JSON yang valid, jadi JSON.parse(atau jQuery $.parseJSON) tidak akan berfungsi.

Salah satu caranya adalah dengan menggunakan eval"parse" JSON "tidak valid", dan kemudian stringify"mengubahnya" menjadi JSON yang valid.

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

Saya sarankan daripada mencoba untuk "memperbaiki" JSON Anda yang tidak valid, Anda mulai dengan JSON yang valid di tempat pertama. Bagaimana strcara dihasilkan, itu harus diperbaiki di sana, sebelum itu dihasilkan, bukan setelah.

EDIT : Anda bilang (dalam komentar) string ini disimpan dalam atribut data:

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

Saya sarankan Anda memperbaikinya di sini, jadi bisa saja JSON.parsed. Pertama, baik kunci dan nilainya perlu dikutip dalam tanda kutip ganda. Seharusnya terlihat (atribut tunggal yang dikutip dalam HTML valid):

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

Sekarang, Anda bisa menggunakan JSON.parse(atau jQuery $.parseJSON).

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

jQuery.parseJSON

str = jQuery.parseJSON(str)

Edit. Ini asalkan Anda memiliki string JSON yang valid

Petani atau
sumber
1
benar saya melihat pertanyaan sebagai bagaimana mengkonversi string JSON ke objek
Farmor
43

Gunakan kode sederhana di tautan di bawah ini:

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

dan mundur

var str = JSON.stringify(arr);
Ronald
sumber
Mengubah jsontext ke objek String melalui String baru (jsontext) mungkin bahkan lebih baik, untuk keamanan tipe.
Analisis Fuzzy
@ fuzzyanalysis: Tidak, pembungkus primitif tidak boleh digunakan.
Ry-
1
JSON.parse () harus menjadi jawaban yang diterima di sini sebagaimana dinyatakan oleh @LouiseMcMahon
pixel 67
24

Saya harap fungsi kecil ini mengubah string JSON yang tidak valid menjadi string yang valid.

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+'"'})         
}

Hasil

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…}
allenhwkim
sumber
Kami mencoba untuk membatalkan verifikasi b menggunakan JSON.parse kode kami dan ini sepertinya solusi yang bagus. Kami masih harus menangani penggantian terus-menerus dengan tangan, tetapi setidaknya ini memungkinkan untuk memuat kasus-kasus itu.
ravemir
1
Hampir sempurna. Tidak berfungsi saat : berada di salah satu nilai.
seler
9

Gunakan dengan hati-hati (karena eval()):

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

panggil sebagai:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );
Tomalak
sumber
3
Untuk pemilih bawah anonim. Saya menantang Anda untuk memberikan solusi yang lebih baik. Selain itu alasan untuk memilih-turun akan menyenangkan.
Tomalak
1
@Rocket: Anda salah. a) eval()adalah satu-satunya cara untuk melakukannya. b) Saya memperingatkan OP tentang hal itu. c) Lihatlah jawaban Matius Crumley dan pikirkan penjelasan yang lebih baik. (Oh, dan d) pernyataan eval()itu buruk tidak masuk akal dalam bentuk umum ini.)
Tomalak
2
@Rocket: Ah, kesalahpahaman di sana. Maaf, saya pikir pemungutan suara itu milik Anda. :)
Tomalak
1
@ Kuboslav: Ini berfungsi dengan baik, apakah Anda bahkan mengujinya? Dia melakukan eval("var x = " + str + ";")JS yang benar-benar valid. Anda tidak perlu melakukannya var x = ({a:12}).
Rocket Hazmat
2
@kuboslav Tidak berfungsi di IE7 karena IE7 tidak memiliki dukungan JSON asli. Ini akan mulai berfungsi segera setelah Anda gunakan json2.js. Jangan jadi pemicu-senang.
Tomalak
4

Penafian: jangan coba ini di rumah, atau untuk apa pun yang mengharuskan pengembang lain menganggap Anda serius:

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

Di sana, saya melakukannya.
Cobalah untuk tidak melakukannya, eval itu BURUK untuk Anda. Seperti diceritakan di atas, gunakan JSON shim Crockford untuk peramban yang lebih lama (IE7 dan di bawah)

Metode ini mengharuskan string Anda menjadi javascript yang valid , yang akan dikonversi ke objek javascript yang kemudian dapat diserialisasi ke JSON.

sunting: diperbaiki seperti yang disarankan Rocket.

Gonchuki
sumber
Seharusnya JSON.stringify(eval('('+str+')'));, bukan saya memaafkan eval, tetapi string-nya JSON tidak valid sehingga JSON.parsetidak berfungsi.
Rocket Hazmat
4

Saya memberikan jawaban saya untuk seseorang yang tertarik pada utas lama ini.

Saya membuat parser data HTML5 * untuk plugin dan demo jQuery yang mengubah string JSON yang rusak menjadi objek JavaScript tanpa menggunakan eval().

Itu dapat melewatkan atribut data HTML5- * di bawah:

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

ke dalam objek:

{
    hello: "world"
}
tokkonopapa
sumber
2

Douglas Crockford memiliki konverter, tetapi saya tidak yakin ini akan membantu dengan JSON yang buruk menjadi JSON yang baik.

https://github.com/douglascrockford/JSON-js

Seth
sumber
Ini tidak terlalu membantu, karena string tersebut bukan JSON yang valid.
Rocket Hazmat
2

Ada cara yang lebih sederhana untuk mencapai prestasi ini, cukup bajak atribut onclick elemen dummy untuk memaksa pengembalian string Anda sebagai objek JavaScript:

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

Berikut ini demo: http://codepen.io/csuwldcat/pen/dfzsu (buka konsol Anda)

csuwldcat
sumber
2

Anda perlu menggunakan "eval" lalu JSON.stringify lalu JSON.parse ke hasilnya.

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

masukkan deskripsi gambar di sini

Negi Rox
sumber
1

Anda harus menulis kurung bundar, karena tanpa mereka evalakan menganggap kode di dalam kurung keriting sebagai blok perintah.

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

Taruhan terbaik dan teraman Anda adalah JSON5 - JSON untuk Manusia . Itu dibuat khusus untuk use case itu.

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>

dereli
sumber
1

Menggunakan Function baru () lebih baik daripada eval, tetapi masih harus digunakan dengan input yang aman.

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 }

Sumber: MDN , 2ality

SamGoody
sumber
0

Untuk contoh sederhana Anda di atas, Anda dapat melakukan ini menggunakan 2 pengganti regex sederhana:

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

Peringatan besar : Pendekatan naif ini mengasumsikan bahwa objek tidak memiliki string yang mengandung karakter 'atau :. Sebagai contoh, saya tidak bisa memikirkan cara yang baik untuk mengubah objek-string berikut ke JSON tanpa menggunakan eval:

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

Hanya untuk kebiasaannya, Anda dapat mengonversi string Anda melalui 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>

Moritz Roessler
sumber
0

var str = "{halo: 'dunia', tempat: ['Afrika', 'Amerika', 'Asia', 'Australia']}" var fStr = str .replace (/ ([Az] *) (:) / g, '"$ 1":') .replace (/ '/ g, "\" ")

console.log (JSON.parse (fStr))masukkan deskripsi gambar di sini

Maaf saya di ponsel saya, ini foto.

Francis Leigh
sumber
0

Solusi dengan satu regex dan tidak menggunakan eval:

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

Ini saya percaya harus bekerja untuk beberapa baris dan semua kemungkinan kemunculan (/ g flag) dari tanda kutip tunggal 'string' diganti dengan tanda kutip ganda "string".

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

Mungkin Anda harus mencoba ini:

str = jQuery.parseJSON(str)
bagaimana kabar
sumber
Pertanyaan ditentukan "atau jQuery" dan ini adalah solusi sempurna jika Anda memilikinya tersedia.
Ecropolis