JSON sözdizimi bir nesnede yinelenen anahtarlara izin veriyor mu?


206

Bu geçerli json mu?

{
    "a" : "x",
    "a" : "y"
}

http://jsonlint.com/ evet diyor.

http://www.json.org/ yasak olduğu hakkında hiçbir şey söylemez.

Ama belli ki pek mantıklı değil, değil mi? Çoğu uygulama muhtemelen hashtable kullanır, bu yüzden zaten geçersiz kılınır.


1
C # 'ın Json.NET, aDictionary<string, string>
Sam Leach

Herkes buraya JSON dizelerinde yinelenen değerler bulmak için bir çözüm
umuyorsa

jsonlint.com evet diyor. değil, son anahtar / değer çifti hariç tümünü kaldırır ve geçerli kılar, bu geçerli kılar
Tim

7
Sonra standart bozuldu
Brad Thomas

1
Bir anahtar olarak "-" anahtar adını kullandım ve değer, yorum olarak tek bir dize satırıdır. Umarım hiçbir ayrıştırıcı bu konuda şikayet etmez.
Lothar

Yanıtlar:


127

Kaynaktan standart (s, ii.) :

Diğer standartların, JSON metin biçimine sıkı sıkıya bağlı kalarak buna karşılık gelmesi ve çeşitli kodlama ayrıntılarına kısıtlamalar getirmesi beklenmektedir. Bu tür standartlar belirli davranışlar gerektirebilir. JSON kendisi davranış belirtmez.

Daha sonra standartta (p. 2), bir JSON nesnesinin belirtimi:

Bir nesne yapısı, sıfır veya daha fazla ad / değer çiftini çevreleyen bir çift süslü parantez jetonu olarak temsil edilir. Ad bir dizedir. Her adı tek bir iki nokta işareti izler ve adı değerden ayırır. Tek bir virgül belirteci, bir değeri aşağıdaki addan ayırır.

JSON Nesnesi Diyagramı

Yinelenen anahtarların geçersiz veya geçerli olduğundan bahsetmez, bu nedenle spesifikasyona göre, izin verildiği anlamına geleceğini güvenle kabul ederim.

JSON kütüphanelerin Bu çoğu uygulamaları yapmak değil çünkü ilk alıntının, standardına does not çatışma yinelenen anahtarlar kabul edin.

İşte C ++ standart kitaplığıyla ilgili iki örnek. Bazı JSON nesnelerinin serisini kaldırırken, std::mapyinelenen anahtarları reddetmek mantıklı olacaktır. Ancak bazı JSON nesnelerini serileştirirken, std::multimapyinelenen anahtarları normal olarak kabul etmek mantıklı olacaktır.


5
@PatrickGoley söz json.org üzerinde bu geçerli olmadığı anlamına gelir benzersizliği ima anahtar / değer çiftleri kümesi denir gibi olsa da ben bir cevap olarak kabul edebilir sanırım.
kelepçe

8
@clamp json.org standart değildir ve bildiğim kadarıyla Emca International tarafından işletilmemektedir. json.org anonim olarak sunuluyor. Bu şartname: ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf o json.org diyor nedir alakalı değildir.
Timothy Shields

5
@clamp std::multimapAz önce eklediğim örneği ele alalım . Olası yinelenen anahtarlarla bir JSON nesnesi olarak serileştirilebilir.
Timothy Shields

1
@clamp bir dizi anahtar / değer çifti olmak yinelenen adları engellemez. {"a":1,"a":2}iki ayrı anahtar / değer çifti kümesidir. Gerçekten de, {"a":1,"a":1}sadece bir öğeye sahip olan bir dizi anahtar / değer çifti olarak düşünülebilir. Tekrarlanması gerçeği, sadece sözdizimsel bir tuhaflık olarak düşünülebilir. Daha iyi bir tanım, "Bir nesne, dizelerden (isimler) değerlere kısmi bir fonksiyondur."
Marcelo Cantos

2
@TimothyShields Ve bağlandığınız bu standart, "JSON sözdizimi, ad olarak kullanılan dizelere herhangi bir kısıtlama getirmez, ad dizelerinin benzersiz olmasını gerektirmez ve ad / değer çiftlerinin sıralamasına herhangi bir önem vermez" der.
Charles

136

Kısa cevap: Evet ama önerilmez.
Uzun cevap: Geçerli olarak adlandırdığınız şeye bağlıdır ...


ECMA-404 "JSON Veri Değişimi Sözdizimi", yinelenen adlar (anahtarlar) hakkında hiçbir şey söylemez.


Ancak, RFC 8259 "JavaScript Nesne Gösterimi (JSON) Veri Değişim Biçimi" diyor:

Bir nesnenin içindeki adlar benzersiz olmalıdır.

Bu bağlamda GEREKEN belirtildiği gibi anlaşılmalıdır BCP 14 :

GEREKEN Bu kelime, ya da sıfat "ÖNERİLEN", orada belirli bir öğeyi göz ardı etmek gibi belirli durumlarda geçerli nedenler bulunabilir, fakat bütün ifadeler anlaşılmış olmalı ve dikkatlice farklı bir rota seçmeden önce tartılan anlamına gelir.


RFC 8259 benzersiz adların (anahtarlar) neden iyi olduğunu açıklar:

İsimleri benzersiz olan bir nesne, bu nesneyi alan tüm yazılım uygulamalarının ad-değer eşlemeleri üzerinde anlaşmaya varması anlamında birlikte çalışabilir. Bir nesnenin içindeki adlar benzersiz olmadığında, böyle bir nesneyi alan yazılımın davranışı tahmin edilemez. Birçok uygulama yalnızca soyadı / değer çiftini rapor eder. Diğer uygulamalar bir hatayı bildirir veya nesneyi ayrıştırmaz ve bazı uygulamalar yinelemeler dahil tüm ad / değer çiftlerini bildirir.



Ayrıca, Serguei'nin yorumlarda belirttiği gibi: ECMA-262 "ECMAScript® Dil Spesifikasyonu", şunları okur:

Bir nesne içinde yinelenen ad Dizeleri olduğunda, aynı anahtar için sözcük olarak önceki değerlerin üzerine yazılır.

Başka bir deyişle, son değer kazanır.


Douglas Crockford ( JSON'un yaratıcısı) tarafından Java uygulamasıyla yinelenen adlara sahip bir dizeyi ayrıştırmaya çalışmak bir istisna ile sonuçlanır :

org.json.JSONException: Duplicate key "status"  at
org.json.JSONObject.putOnce(JSONObject.java:1076)

1
JSON'un geçerli bir javascript olması gerekiyor, bu nedenle yinelenen anahtarların değişmez anahtarlarda geçerli JS olup olmadığını kontrol etmek önemlidir. V8 onları kabul ediyor gibi görünüyor: d8 -e 'x={"a":1,"a":2}; print(x.a);'Bu 2. basar.
Ben Crowell

5
Ayrıca ECMA-262 spesifikasyonu JSON.parse()açıkça söylüyor In the case where there are duplicate name Strings within an object, lexically preceding values for the same key shall be overwritten.(diğer bir deyişle son değer kazanır).
Serguei

4
@BenCrowell: Bildiğim kadarıyla JSON'un geçerli JavaScript olması gerekmiyor ve olmadığı durumlar var, bkz. Timelessrepo.com/json-isnt-a-javascript-subset . Bununla birlikte, elbette JavaScript'ten büyük ölçüde ilham aldı (JSON spesifikasyonunda bile bunu söylüyor).
Simon Touchtech

2
Javascript "katı mod" kullanırken, iki özdeş anahtar varsa, krom ikinci anahtar / değer çiftini kullanacak ve birincisini yok sayacaktır. IE11 bir istisna atar.
Shahar

18

JSON biçimini belirten 2 belge vardır:

  1. http://json.org/
  2. https://tools.ietf.org/html/rfc7159

Kabul edilen cevap 1. belgeden alıntıdır. Bence ilk belge daha açık, ancak ikinci belge daha fazla ayrıntı içeriyor.

İkinci belge şöyle diyor:

  1. Nesneler

    Bir nesne yapısı, sıfır veya daha fazla ad / değer çiftini (veya üyeyi) çevreleyen bir çift süslü parantez olarak temsil edilir. Ad bir dizedir. Her addan sonra, adı değerden ayıran tek bir iki nokta üst üste gelir. Tek bir virgül, bir değeri aşağıdaki addan ayırır. Bir nesnenin içindeki adlar benzersiz olmalıdır.

Bu nedenle, yinelenen bir isme sahip olmak yasak değildir, ancak önerilmez.


10

Hem XML hem de JSON kabul eden bir API ile uğraşırken benzer bir soru ile karşılaştım, ancak kabul edilen JSON'da yinelenen anahtarlar olmasını beklediğinizi nasıl işleyeceğini belgelemiyorum.

Örnek JSON örneğinizin geçerli bir XML temsilidir:

<object>
  <a>x</a>
  <a>y</a>
</object>

Bu JSON'a dönüştürüldüğünde aşağıdakileri elde edersiniz:

{
  "object": {
    "a": [
      "x",
      "y"
    ]
  }
}

Yinelenen anahtarları başka bir anahtarla adlandırabileceğiniz bir dilden gelen doğal bir eşleme, burada potansiyel en iyi uygulama referansı olarak kullanılabilir.

Umarım birine yardım eder!


5

JSON spec şunları söylüyor:

Bir nesne, sıralanmamış bir ad / değer çifti kümesidir.

Burada önemli olan kısım "sıralanmamıştır": anahtarların benzersizliğini ifade eder, çünkü belirli bir çifti belirtmek için kullanabileceğiniz tek şey anahtardır.

Buna ek olarak, çoğu JSON kütüphanesi, JSON nesnelerini, anahtarların benzersiz olduğu garanti edilen karma haritalara / sözlüklere serisini kaldırır. Yinelenen anahtarlarla bir JSON nesnesinin serisini kaldırdığınızda ne olur, kitaplığa bağlıdır: Çoğu durumda, bir hata alırsınız veya her yinelenen anahtar için yalnızca son değer dikkate alınır.

Örneğin, Python'da json.loads('{"a": 1, "a": 2}')geri döner {"a": 2}.


23
sırasız benzersizliği ima eder mi? Bence set burada kullanılan kelime
Patrick Goley

8
Sırasız bir renk koleksiyonu: Mavi, Yeşil, Yeşil, Mavi, Kırmızı, Mavi, Yeşil - Kopyaları var.
Timothy Shields

5
Alıntıladığınız metin ifadesi, "Bir nesne, ad / değer çiftlerinin sırasız bir kümesidir," JSON spesifikasyonunda görünmüyor ...
Timothy Shields

6
Şimdi json.org'dan alıntı yaptığınızı görüyorum. Görevlilere 'yakın' ama şartname değil. Sayfanın üst kısmında json.org'da tekrarlanan spesifikasyona bir bağlantı vardır. Spesifikasyonu ararsanız, "sırasız" kelimesi görünmez ve "set" kelimesi yalnızca JSON nesneleriyle ilişkili olmayan bağlamlarda görünür.
Timothy Shields

5
"Sıralanmamış ad / değer çifti kümesi" yazdığına dikkat edin , çiftler isim değil. Olduğu, { (a,b), (a,c) } olduğu benzersiz bir set. Bu yüzden teknik olarak json.org tanımı altında {"a":1,"a":2}geçerlidir, ancak geçerli {"a":1,"a":2,"a":1}değildir. Ayrıca ECMA-404 (gerçek standart) "set" kelimesini kullanmaktan kaçındığını unutmayın :An object structure is represented as a pair of curly bracket tokens surrounding zero or more name/value pairs.
Serguei

3

Benzersiz olmalı, benzersiz OLMALIDIR anlamına gelmez. Ancak, belirtildiği gibi, bazı ayrıştırıcılar başarısız olurken, diğerleri sadece ayrıştırılan son değeri kullanır. Ancak, spec kopyaları izin vermek için biraz temizlenmiş, o zaman JSON HTML veya başka bir formata dönüştüren bir olay işleyicisi olabilir bir kullanım görebiliyordu ... bu gibi durumlarda mükemmel geçerli olacaktır JSON'ı ayrıştırın ve başka bir belge biçimi oluşturun ...

[
  "div":
  {
    "p":"hello",
    "p":"universe"
  }
  "div":
  {
    "h1":"Heading 1",
    "p":"another paragraph"
  }
]

daha sonra örneğin html'ye kolayca ayrıştırılabilir

<body>
 <div>
  <p>hello</p>
  <p>universe</p>
 </div>
 <div>
  <h1>Heading 1</h1>
  <p>another paragraph</p>
 </div>
</body>

Sorunun ardındaki mantığı görebiliyorum ama durduğu gibi ... Buna güvenmem.


İlk örneğinizin dizisinde virgül eksik. Ayrıca, kendisi ile tutarsızdır. Bir sözlüğü sıralı koleksiyon olarak kullanacaksanız, dış diziniz de sadece bir nesne olmalıdır. Yani {"div":{"p":"hello","p":"universe"}, "div":{"h1":"Heading 1","p":"another paragraph"}}. Şimdi, birçok kişi ve çerçeve JSON nesnelerini sırasız sözlükler olarak görüyor, ancak JavaScript ve örneğin MongoDB'nin API'si sözlükler içindeki anahtarların sırasına güveniyor, bu nedenle önerdiğiniz (sıralı sözlükler) duyulmuyor. Sadece özel bir ayrıştırıcıya ihtiyacınız var.
binki

2

Amaç sormak, farklı cevaplar vardır:

Nesneleri serileştirmek için JSON (JavaScriptObjectNotation) kullanarak, her sözlük öğesi bağımsız bir nesne özelliğiyle eşleşir, böylece aynı özellik için bir değer tanımlayan farklı girdilerin bir anlamı yoktur.

Ancak, aynı soruyu çok özel bir kullanım durumundan aldım: API testi için JSON örnekleri yazarken, kullanılabilirliği bozmadan JSON dosyamıza nasıl yorum ekleyeceğini merak ediyordum. JSON spec yorumları bilmiyor, bu yüzden çok basit bir yaklaşım buldum:

JSON örneklerimize yorum yapmak üzere yinelenen anahtarlar kullanmak için . Misal:

{ "property1" : "value1", "REMARK" : "... prop1 controls ...", "property2" : "value2", "REMARK" : "... value2 raises an exception ...", }

Kullandığımız JSON serileştiricilerinin bu "HATIRLATMA" kopyaları ile herhangi bir sorunu yoktur ve uygulama kodumuz bu küçük ek yükü yok sayar.

Bu nedenle, uygulama katmanında hiçbir anlam olmamasına rağmen, bu kopyalar bizim için JSON'un kullanılabilirliğini bozmadan test örneklerimize yorum eklemek için değerli bir geçici çözüm sunar.


Bu kötü bir fikir. Yinelenen anahtarlar ekleyerek, içindeki verileri okumasanız bile, tanımlanmamış davranışa güveniyorsunuz. Crockford'un JSON-java ayrıştırıcısı gibi bazı ayrıştırıcılar bir istisna atar ve verileri ayrıştırmayı reddeder.
Richard Smith

Aslında çevremizde mükemmel çalışıyor, bu yüzden ihtiyaçlarımı karşılıyor, ancak bunun bir tür özelliğin dışında olduğunu kabul
etsem bile

@RichardSmith Ayrıştırıcıların ve daha yeni ES özelliklerinin davranışı tanımladığını söyleyebilirim.
binki

2

Gönderme ve cevaplama, çünkü standartlar hakkında çok sayıda eski fikir ve karışıklık var. Aralık 2017 itibariyle iki rakip standart vardır:

RFC 8259 - https://tools.ietf.org/html/rfc8259

ECMA-404 - http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf

json.org ECMA-404 olduğuna işaret standart, ancak bu site bir otorite olmak görünmüyor. Onun 'adil Burada önemli olanı ECMA'yı otorite, (benzersiz anahtarlar ile ilgili olarak) standartlarına arasındaki tek fark dikkate düşünürken RFC 8259 tuşları diyor ki gereken benzersiz olması ve ECMA-404 onlar diyor gerekmez olmak benzersiz.

RFC 8259:

"Bir nesnenin içindeki isimler benzersiz olmalıdır."

Bunun gibi tüm büyük harflerde "olması gereken" kelimesi, RFC dünyasında, başka bir standartta (BCP 14, RFC 2119 - https://tools.ietf.org/html/rfc2119 ) özel olarak tanımlanan bir anlama sahiptir ,

  1. Bu kelime veya "ÖNERİLEN" sıfatının, belirli durumlarda belirli bir öğeyi göz ardı etmek için geçerli nedenler olabileceği anlamına gelir, ancak farklı bir ders seçilmeden önce tüm çıkarımların anlaşılması ve dikkatle tartılması gerekir.

ECMA-404:

"JSON sözdizimi, ad olarak kullanılan dizelere herhangi bir kısıtlama getirmez, ad dizelerinin benzersiz olmasını gerektirmez ve ad / değer çiftlerinin sırasına herhangi bir önem vermez."

Yani, nasıl dilerseniz dilerseniz sözdizimsel olarak geçerli JSON .

RFC 8259'da benzersiz anahtar öneri için verilen neden,

İsimleri benzersiz olan bir nesne, bu nesneyi alan tüm yazılım uygulamalarının ad-değer eşlemeleri üzerinde anlaşmaya varması anlamında birlikte çalışabilir. Bir nesnenin içindeki adlar benzersiz olmadığında, böyle bir nesneyi alan yazılımın davranışı tahmin edilemez. Birçok uygulama yalnızca soyadı / değer çiftini rapor eder. Diğer uygulamalar bir hatayı bildirir veya nesneyi ayrıştırmaz ve bazı uygulamalar yinelemeler dahil tüm ad / değer çiftlerini bildirir.

Başka bir deyişle, RFC 8259 bakış açısından geçerlidir, ancak ayrıştırıcınız engel olabilir ve eğer varsa, değerin bu anahtarla eşleştirileceği konusunda herhangi bir söz yoktur. ECMA-404 bakış açısından (şahsen otorite olarak alacağım) geçerli. Benim için bu ayrıştırmayı reddeden herhangi bir ayrıştırıcının bozuk olduğu anlamına gelir. En azından bu standartların her ikisine göre ayrıştırılmalıdır. Ancak yerel seçim nesnenize nasıl dönüştüğü, her durumda, benzersiz anahtarlar veya değil, tamamen çevreye ve duruma bağlıdır ve bunların hiçbiri başlangıçta standart değildir.


json.org aslında ECMA standardizasyonundan önce gelir. Aslında Crockford kendisi tarafından kurulmuş olduğuna inanıyorum (bu yüzden kitabı için utanmaz bir fişi vardır). Bu noktada JSON'un yetkisiydi.
maksimum

1

ECMA JSON standardında tanımlanmamıştır . Ve genel olarak konuşursak, standartta bir tanım eksikliği, "Bu çalışmayı her yerde aynı şekilde sayma" anlamına gelir.

Bir kumarbazsanız, "birçok" JSON motoru çoğaltmaya izin verir ve sadece son belirtilen değeri kullanır. Bu:

var o = {"a": 1, "b": 2, "a": 3}

Bu olur:

Object {a: 3, b: 2}

Ama eğer bir kumarbaz değilseniz, buna güvenmeyin !


1

Standart bunu söylüyor:

Programlama dilleri, nesneleri destekleyip desteklemediklerine ve öyleyse nesnelerin hangi özellikleri ve kısıtlamaları sunduğuna göre büyük ölçüde farklılık gösterir. Nesne sistemlerinin modelleri çılgınca ıraksak olabilir ve gelişmeye devam etmektedir. Bunun yerine JSON, ad / değer çiftlerinin koleksiyonlarını ifade etmek için basit bir gösterim sağlar. Çoğu programlama dili, bu tür koleksiyonları temsil etmek için kayıt, yapı, dikte, harita, karma veya nesne gibi adlara sahip olabilecek bazı özelliklere sahiptir.

Hata en azından node.js'de. Bu kod node.js'de başarılı olur.

try {
     var json = {"name":"n","name":"v"};
     console.log(json); // outputs { name: 'v' }
} catch (e) {
     console.log(e);
}

1
Bu bir hata değil ve alıntıladığınız bölüm neden olmadığını açıklıyor: farklı diller farklı davranıyor ve JSON ayrıştırıcıları bu dil için en doğal olanı yapacak. Her durumda, bu cevap user454322'nin yukarıda söylemediği hiçbir şey eklemiyor.
Richard Smith

1

Internet Mühendislik Görev Gücü (IETF) tarafından yayınlanan JSON için geçerli standart olan RFC-7159'a göre, "Bir nesnenin içindeki adlar benzersiz olmalıdır" yazıyor. Bununla birlikte, IETF belgelerinde kullanılan terminolojiyi tanımlayan RFC-2119'a göre, "aslında" anlamına gelir "kelimesi ... ... belirli durumlarda belirli bir öğeyi görmezden gelmek için geçerli nedenler olabilir, ancak tüm çıkarımlar anlaşılmalı ve farklı bir kurs seçmeden önce dikkatlice tartılır. " Bunun temel olarak anlamı, benzersiz anahtarlara sahip olmanın tavsiye edilirken, bir zorunluluk olmamasıdır. Bir JSON nesnesinde yinelenen anahtarlara sahip olabiliriz ve yine de geçerli olur.

Pratik uygulamadan, JSON'da yinelenen anahtarlar bulunduğunda son anahtarın değerinin dikkate alındığını gördüm.


0

C # 'da bir seriyi çıkarırsanız Dictionary<string, string>, son anahtar değer çiftini alır:

string json = @"{""a"": ""x"", ""a"": ""y""}";
var d = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
// { "a" : "y" }

eğer serileştirmeyi denersen

class Foo
{
    [JsonProperty("a")]
    public string Bar { get; set; }

    [JsonProperty("a")]
    public string Baz { get; set; }
}

var f = JsonConvert.DeserializeObject<Foo>(json);

bir Newtonsoft.Json.JsonSerializationExceptionistisna elde edersiniz .


2
i (hepsi değilse de) uygulamaların ne olduğunu tahmin, ama JSON şartname olarak geçerli olup olmadığını soruma cevap vermez.
kelepçe

@svidgen: Bu Microsoft'un uygulaması bile değil ... üçüncü taraf bir kütüphane.
BoltClock

@BoltClock Ah, touche.
svidgen
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.