JSON.stringify, özelliklerden alıntı yapmadan?


100

Yanlış JSON biçimi kullanan bir hizmet kullanıyorum (özelliklerin etrafında çift tırnak işareti yok). Bu yüzden göndermem gerek

{ name: "John Smith" } onun yerine { "name": "John Smith" }

Bu benim hizmetim olmadığı için bu format değiştirilemez.

Yukarıdaki gibi bir JavaScript nesnesini biçimlendirmek için stringify yönlendirmeyi bilen var mı?

Yanıtlar:


120

Bu basit normal ifade çözümü, çoğu durumda JSON özellik adlarını alıntı yapmak için çalışır:

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"}

Aşırı zor vaka:

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

Bunu düzelttiği için Rob W'ye özel teşekkürler.

Sınırlamalar

Normal durumlarda yukarıda belirtilen regexp çalışacaktır, ancak matematiksel olarak JSON formatını her durumda çalışacak şekilde bir düzenli ifade ile tanımlamak imkansızdır (regexp ile aynı sayıda küme parantezini saymak imkansızdır). JSON dizesini yerel işlev aracılığıyla resmi olarak ayrıştırarak ve yeniden seri hale getirerek teklifleri kaldırmak için yeni bir işlev oluşturun:

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

Örnek: https://jsfiddle.net/DerekL/mssybp3k/


3
-1 de ben değildim, ama soruyu dikkatlice okumalısın. OP'nin bir nesneyi ayrıştırmak / değerlendirmek yerine (bozuk) json olarak kodlaması gerekir.
Salman A

7
@Derek Bu yöntem güvenilir değildir . Örneğin, şu girişi alın: {"foo":"e\":bar"}(geçerli JSON), {foo:e:bar"}(...) olur !
Rob W

1
@Derek /\\\"/basitleştirilebilir /\\"/. Global bayrağı eklemeyi unutmayın /\\"/g, aksi takdirde çoklu dizgelerde kırılır \". Rastgele karaktere gelince , düzenleyicinin boğulması durumunda asla gerçek bir U + FFFF kullanın, ancak bir kaçış dizisi kullanın. Geri döndürme normal ifadesi haline gelir /\uFFFF/g.
Rob W

2
@Derek 朕 會 功夫 normal ifadeniz /\"([^(\")"]+)\":/gbasitleştirilebilir /"([^"]+)":/g, bkz. Regex101.com/r/qnz0ld/2
tanguy_k

1
@endriu Bu durumda sadece boş değerler için ek bir kontrol ekleyin.
Derek 朕 會 功夫

19

Görünüşe göre bu, aradığınız basit bir Object toString yöntemi.

Node.js'de bu, util nesnesi kullanılarak ve util.inspect (yourObject) çağrısı yapılarak çözülür. Bu size istediğiniz her şeyi verecektir. yöntemin uygulama derinliği dahil daha fazla seçenek için bu bağlantıyı izleyin. http://nodejs.org/api/util.html#util_util_inspect_object_options

Yani, aradığınız şey temelde bir JSON dönüştürücü değil, bir nesne denetçisi. JSON biçimi, tüm özelliklerin çift tırnak içine alınması gerektiğini belirtir. Bu nedenle, istediğinizi yapacak JSON dönüştürücüler olmayacak, çünkü bu sadece bir JSON formatı değildir. Buradaki özellikler: https://developer.mozilla.org/en-US/docs/Using_native_JSON

Sunucunuzun diline bağlı olarak, diziye veya denetlemeye itiraz ihtiyacınız olan şeydir.


1
Çok teşekkür ederim! Bu tam olarak aradığım şeydi. Ws sunucusundan oyunuma veri göndermek için json kullanıyorum ve buna inanıyorum ya da inanmıyorum, özellik adlarının etrafındaki ekstra tırnak işaretleriyle uğraşmak zorunda kalmamak çok büyük miktarda veri tasarrufu sağlıyor! Sadece açıklığa kavuşturmak için, .toSource()nodejs içinde de iyi çalışır, ancak dizilerdeki nesnelerde çalışmaz. İnceleme util, dizilerdeki diziler ve nesneler için çalışıyor ki bu harika, bayıldım.
NiCk Newman

3
util.inspect()bir Neo4j sorgusuna bir nesne yazarken, aynı anda birden fazla parametre ayarlamak için harika çalıştı.
agm1984

1
Nodejs linkinden:> util.inspect () yöntemi, hata ayıklama için amaçlanan nesnenin bir dize gösterimini döndürür. Util.inspect'in çıktısı herhangi bir zamanda değişebilir ve programa bağlı olmamalıdır.
Peter Roehlen

5

JSON formatını tanımlayan tarafından oluşturulan bir ayrıştırıcının kaynak koduna bakabilirsiniz . İşlev çağrılarını arayın : bunlar bir değeri tırnak içine alır. Anahtarlar 326 ve 338 satırlarında alıntılanmıştır .json2.js quote

Değişiklikten sonra kitaplığı dahil etmeyin. Bunun yerine, yalnızca ilgili ( stringify) kısmı alın veya en azından JSONbaşka bir şeyle değiştirin , örn. FAKEJSON.

Örneğin, FAKEJSONyalnızca şu tanımlı bir nesne stringify: http://jsfiddle.net/PYudw/


Tamamen JavaScript ile yapabiliyorsanız neden fazladan bir kitaplığa ihtiyacınız var?
Derek 朕 會 功夫

Bu iyi bir fikir. Ben, repo çatal tırnak kaldırmak ve bunu olduğundan temizlemek yapmak FAILJSON gibi bir şey alaycı için JSON nesnesi adlandırmak istiyorum değil gerçek JSON nesnesi veya gerçek JSON ile çalışıyor.
RichardTowers

@Derek Kütüphane bir bütün olarak dahil edilmemelidir. Sadece JSON.stringifyparçayı alın ve alıntıları kaldırın. Kitaplık JSON'u tanımlayan kişi tarafından oluşturulduğundan , sonucun çok geçerli JSON olduğundan oldukça emin olabiliriz.
Rob W

Görünüşe göre bu en iyi yaklaşım.
Derek 朕 會 功夫

Evet, Derek'e katılıyorum. Onun yerine geçen kişi iyi çalışsa da, Crawford'un koduyla kendime daha çok güveniyorum, derek lol'e saygısızlık etmiyorum. .toSource()iyi çalışıyor ancak nesneniz bir serseri dizide ise (ve düğümde olduğum için tarayıcı uyumluluğu bir sorun değil: P), bu yöntemi @RobW sayesinde kullanacağım, jsfiddle bağlantısı görünüyor yükleme sayfasında
takılmak için

4

Servive'i JSONP ile kullanmayı deneyin, sanırım bu formatı kullanırken sunuyorlar.

Aksi takdirde, onlara neden standarda uyması gerektiğine dair iyi bir argüman içeren ayrıntılı bir hata raporu gönderin. Kaynak problemini ortadan kaldırmaktan başka bir çözüm gerçek bir çözüm değildir.

Hızlı-n-kirli düzeltme, dizeyi ayrıştırmadan önce bir normal ifadeden geçirmektir:

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

Yoksa (gibi mevcut javascript JSON ayrıştırıcı ayarlamak için deneyin bu bir Eğer daha sözdizimsel ayrıştırma istiyorsanız).




2

@Derek 朕 會 功夫 Bu yöntemi paylaştığınız için teşekkürler, bir dizi nesnenin dizgisini de destekleyen kodumu paylaşmayı seviyorum.

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(",")
            }}`;
};

1
JSON.stringifyÖrneğin Date'i de kullanmalısınız . Ayrıca dönmek 'null'durumunda obj_from_jsonnull.
Far Dmitry

1
@FarDmitry'nin yükselttiği puanları, saniye if koşulunu şu şekilde değiştirerek if(typeof obj_from_json !== "object" || obj_from_json instanceof Date || obj_from_json === null)
düzelttim

2

Kullanım JSON5.stringify

JSON5 , tırnaksız özellik anahtarları dahil ES5 sözdizimine izin veren bir JSON üst kümesidir . JSON5 referans uygulaması ( json5npm paketi ) JSON5, yerleşik JSONnesne ile aynı argümanlar ve anlambilimlere sahip aynı yöntemlere sahip bir nesne sağlar.

Kullandığınız hizmet büyük olasılıkla bu kitaplığı kullanıyor.


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.