JSON.stringify tanpa tanda kutip pada properti?

98

Saya menggunakan layanan yang menggunakan format JSON yang salah (tidak ada tanda kutip ganda di sekitar properti). Jadi saya perlu mengirim

{ name: "John Smith" } dari pada { "name": "John Smith" }

Format ini tidak dapat diubah karena ini bukan layanan saya.

Adakah yang tahu tentang perutean stringify untuk memformat objek JavaScript seperti di atas?

jadent
sumber

Jawaban:

117

Solusi ekspresi reguler sederhana ini berfungsi untuk menghapus kutipan nama properti JSON dalam banyak kasus:

const object = { name: 'John Smith' };
const json = JSON.stringify(object);  // {"name":"John Smith"}
console.log(json);
const unquoted = json.replace(/"([^"]+)":/g, '$1:');
console.log(unquoted);  // {name:"John Smith"}

Kasus ekstrim:

var json = '{ "name": "J\\":ohn Smith" }'
json.replace(/\\"/g,"\uFFFF");  // U+ FFFF
json = json.replace(/"([^"]+)":/g, '$1:').replace(/\uFFFF/g, '\\\"');
// '{ name: "J\":ohn Smith" }'

Terima kasih khusus kepada Rob W untuk memperbaikinya.

Batasan

Dalam kasus normal, regexp yang disebutkan di atas akan berfungsi, tetapi secara matematis tidak mungkin untuk menggambarkan format JSON dengan ekspresi reguler sedemikian rupa sehingga akan berfungsi di setiap kasus (menghitung jumlah tanda kurung keriting yang sama tidak mungkin dengan regexp.) Oleh karena itu, saya punya buat fungsi baru untuk menghapus tanda kutip dengan mengurai string JSON secara resmi melalui fungsi asli dan melakukan reserialisasi:

function stringify(obj_from_json) {
    if (typeof obj_from_json !== "object" || Array.isArray(obj_from_json)){
        // not an object, stringify using native function
        return JSON.stringify(obj_from_json);
    }
    // Implements recursive object serialization according to JSON spec
    // but without quotes around the keys.
    let props = Object
        .keys(obj_from_json)
        .map(key => `${key}:${stringify(obj_from_json[key])}`)
        .join(",");
    return `{${props}}`;
}

Contoh: https://jsfiddle.net/DerekL/mssybp3k/

Derek 朕 會 功夫
sumber
3
Saya juga bukan saya, tetapi Anda harus membaca pertanyaan itu dengan cermat. OP perlu menyandikan objek ke (rusak) json, bukan mengurai / mengevaluasinya.
Salman A
7
@ Derek Metode ini tidak dapat diandalkan . Misalnya, ambil input ini: {"foo":"e\":bar"}(JSON valid) menjadi {foo:e:bar"}(...)!
Rob W
1
@Derek /\\\"/dapat disederhanakan menjadi /\\"/. Jangan lupa untuk menambahkan bendera global /\\"/g, atau akan merusak string dengan beberapa \". Sedangkan untuk karakter acak, jangan pernah menggunakan U + FFFF literal, jika editor tersedak, tetapi escape sequence. Regex untuk mengembalikan akan menjadi /\uFFFF/g.
Rob W
2
@Derek 朕 會 功夫 regex Anda /\"([^(\")"]+)\":/gdapat disederhanakan /"([^"]+)":/g, lihat regex101.com/r/qnz0ld/2
tanguy_k
1
@endriu Dalam hal ini tambahkan saja pemeriksaan tambahan untuk nilai null.
Derek 朕 會 功夫
18

Sepertinya ini adalah metode Object toString sederhana yang Anda cari.

Di Node.js, hal ini diselesaikan dengan menggunakan objek util dan memanggil util.inspect (yourObject). Ini akan memberikan semua yang Anda inginkan. ikuti tautan ini untuk opsi lainnya termasuk kedalaman penerapan metode. http://nodejs.org/api/util.html#util_util_inspect_object_options

Jadi, yang Anda cari pada dasarnya adalah pemeriksa objek, bukan konverter JSON. Format JSON menentukan bahwa semua properti harus diapit tanda kutip ganda. Karenanya tidak akan ada konverter JSON untuk melakukan apa yang Anda inginkan karena itu bukan format JSON. Spek di sini: https://developer.mozilla.org/en-US/docs/Using_native_JSON

Objek ke string atau inspeksi adalah apa yang Anda butuhkan tergantung pada bahasa server Anda.

fino
sumber
1
Terima kasih banyak! Inilah yang saya cari. Saya menggunakan json untuk memancarkan data melintasi server ws ke permainan saya dan percaya atau tidak, tidak harus berurusan dengan tanda kutip tambahan di sekitar nama properti akan menghemat banyak sekali data! Hanya untuk memperjelas, .toSource()berfungsi dengan baik di dalam nodejs juga, tetapi tidak berfungsi objek dalam array. The utilmemeriksa bekerja untuk array dan objek dalam array yang indah, cinta itu.
NiCk Newman
3
util.inspect()bekerja luar biasa bagi saya saat menulis objek ke kueri Neo4j, untuk menyetel beberapa parameter sekaligus.
agm1984
1
Dari link nodejs:> Metode util.inspect () mengembalikan representasi string dari objek yang dimaksudkan untuk debugging. Output util.inspect dapat berubah kapan saja dan tidak boleh bergantung pada program.
Peter Roehlen
5

Anda dapat melihat kode sumber parser yang dibuat oleh orang yang mendefinisikan format JSON . Cari panggilan fungsi: panggilan ini mengelilingi nilai dengan tanda kutip. Kunci dikutip pada baris 326 dan 338json2.js quote .

Jangan menyertakan pustaka setelah modifikasi. Alih-alih hanya mengambil bagian yang relevan ( stringify), atau setidaknya mengganti JSONdengan yang lain, mis.FAKEJSON.

Misalnya, objek FAKEJSONyang hanya didefinisikan stringify: http://jsfiddle.net/PYudw/

Rob W.
sumber
Mengapa Anda membutuhkan pustaka tambahan saat Anda dapat melakukannya dalam JavaScript murni?
Derek 朕 會 功夫
Ini ide yang bagus. Saya akan membagi repo, menghapus tanda kutip, dan mengganti nama objek JSON menjadi sesuatu yang lucu seperti FAILJSON untuk memperjelas bahwa Anda tidak bekerja dengan objek JSON yang sebenarnya, atau JSON yang sebenarnya.
RichardTowers
@Derek Perpustakaan tidak boleh disertakan secara keseluruhan. Hanya ambil JSON.stringifybagiannya, dan hapus tanda kutipnya. Karena pustaka dibuat oleh orang yang mendefinisikan JSON , kita bisa yakin bahwa hasilnya adalah JSON yang sangat valid.
Rob W
Sepertinya ini pendekatan terbaik.
Derek 朕 會 功夫
Ya, setuju dengan Derek. Meskipun penggantinya berfungsi dengan baik, saya merasa lebih percaya diri dengan kode crawford, tidak ada rasa tidak hormat untuk derek lol. .toSource()berfungsi dengan baik tetapi tidak termasuk jika objek Anda dalam array yang mengecewakan (dan saya berada di node sehingga compat browser tidak menjadi masalah: P) jadi saya akan menggunakan metode ini terima kasih @RobW juga, tautan jsfiddle tampaknya macet di laman pemuatan :(
NiCk Newman
4

Coba gunakan servive dengan JSONP, saya kira mereka menawarkannya saat menggunakan format ini.

Lain, ajukan mereka laporan bug rinci termasuk argumentasi yang baik mengapa harus sesuai dengan standar. Solusi lain selain menghilangkan masalah sumber bukanlah solusi nyata.

Perbaikan cepat-n-kotor mungkin dengan menyalurkan string melalui regex sebelum menguraikannya:

var obj = JSON.parse(str.replace(/(\{|,)\s*(.+?)\s*:/g, '$1 "$2":'));

Atau Anda mencoba menyesuaikan parser JSON javascript yang ada (seperti ini ) jika Anda menginginkan parse yang lebih sintaksis.

Bergi
sumber
3

Menemukan paket NPM yang bagus untuk melakukan ini:

https://www.npmjs.com/package/stringify-object

const stringify = require('stringify-object')

let prettyOutput = stringify(json);

Bekerja dengan baik.

pengguna1543276
sumber
1
Lib ini tidak rekursif.
corysimmons
2

Sintaks warisan Anda harus mudah dimakan oleh YAML, yang merupakan superset dari JSON.

Coba parser dan dumper YAML JavaScript: http://nodeca.github.com/js-yaml/

pengguna1649339
sumber
2

@Derek 朕 會 功夫 Terima kasih telah membagikan metode ini, saya ingin membagikan kode saya yang mendukung merangkai array objek juga.

export const stringifyObjectWithNoQuotesOnKeys = (obj_from_json) => {
    // In case of an array we'll stringify all objects.
    if (Array.isArray(obj_from_json)) {
        return `[${
                    obj_from_json
                        .map(obj => `${stringifyObjectWithNoQuotesOnKeys(obj)}`)
                        .join(",")
                }]` ;
    }
    // not an object, stringify using native function
    if(typeof obj_from_json !== "object" || obj_from_json instanceof Date || obj_from_json === null){
        return JSON.stringify(obj_from_json);
    }
    // Implements recursive object serialization according to JSON spec
    // but without quotes around the keys.
    return `{${
            Object
                .keys(obj_from_json)
                .map(key => `${key}:${stringifyObjectWithNoQuotesOnKeys(obj_from_json[key])}`)
                .join(",")
            }}`;
};
Adel Bachene
sumber
1
Anda harus menggunakan JSON.stringifymisalnya Tanggal juga. Juga kembalikan 'null'jika obj_from_jsonnol.
Far Dmitry
1
Saya baru saja memperbaiki poin yang diangkat oleh @FarDmitry dengan mengubah kondisi kedua jika terlihat seperti ini:if(typeof obj_from_json !== "object" || obj_from_json instanceof Date || obj_from_json === null)
Brunno Vodola Martins
2

Menggunakan JSON5.stringify

JSON5 adalah superset dari JSON yang memungkinkan sintaks ES5, termasuk kunci properti tanpa tanda kutip . Implementasi referensi JSON5 ( json5paket npm ) menyediakan JSON5objek yang memiliki metode yang sama dengan arg dan semantik yang sama seperti bawaanJSON objek .

Sangat mungkin bahwa layanan yang Anda gunakan menggunakan pustaka ini.

Inigo
sumber
1

JSON Beautifier CSVJSON memiliki opsi untuk memberikan tanda kutip pada kunci. Jika Anda hanya menginginkan kodenya, Anda dapat menyalinnya dari repo GitHub. Saya memodifikasi JSON2 Douglas Crockford untuk menambahkan dukungan untuk itu.

Martin Drapeau
sumber
Baru saja mengklik csvjson.com/json_beautifier dan mendapatkan halaman yang jauh berbeda dari yang saya harapkan ... hacked by AnoaGhost
RedactedProfile
Dibersihkan sekarang. Maaf untuk ketidaknyamanannya.
Martin Drapeau