jsonSchema özniteliği koşullu olarak gerekli


106

JsonSchema'da, tanımlı alanların zorunlu olup olmadığını belirtebilirsiniz veya requiredözniteliği kullanmazsınız :

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "header": {
            "type": "object",
            "properties": {
                "messageName": {
                    "type": "string"
                },
                "messageVersion": {
                    "type": "string"
                }
            },
            "required": [
                "messageName",
                "messageVersion"
            ]
        }
    },
    "required": [
        "header"
    ]
}

Bazı durumlarda messageVersionalanın zorunlu olmamasını isterim . Bu alanın zorunlu olmasını koşullu yapmanın bir yolu var mı?


Evet, mümkün olmalı. Verilerdeki hangi bilgiler zorunluluğu tetikler?
jruizaranguren

@SarveswaranMeenakshiSundaram - Sadece json şemasının
v4'ünü

3. versiyonda bu mümkün mü?
Sarvesh

@SarveswaranMeenakshiSundaram - Bilmiyorum. Deneyin ve lütfen bize bildirin!
tom redfern

Yanıtlar:


281

Durumunuza bağlı olarak, birkaç farklı yaklaşım vardır. Bir alana şartlı olarak ihtiyaç duymanın dört farklı yolunu düşünebilirim.

Bağımlılıklar

dependenciesAnahtar kelime bir koşullu varyasyon requiredanahtar kelime. Foreach özelliği dependencies, doğrulanan JSON'da özellik mevcutsa, bu anahtarla ilişkili şema da geçerli olmalıdır. "Foo" özelliği mevcutsa, "bar" özelliği gereklidir

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "dependencies": {
    "foo": { "required": ["bar"] }
  }
}

Şema yalnızca requiredanahtar kelimeyi içeriyorsa kısa bir form da vardır .

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "dependencies": {
    "foo": ["bar"]
  }
}

Ima

Koşulunuz bir alanın değerine bağlıysa, çıkarım adı verilen bir mantıksal mantık kavramı kullanabilirsiniz. "A, B'yi ima eder" etkin bir şekilde, eğer A doğruysa B'nin de doğru olması gerektiği anlamına gelir. Çıkarım aynı zamanda "! A veya B" olarak da ifade edilebilir. Ya "foo" özelliği "bar" a eşit değildir veya "bar" özelliği gereklidir . Veya başka bir deyişle: "foo" özelliği "bar" a eşitse, "bar" özelliği gerekir.

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "anyOf": [
    {
      "not": {
        "properties": {
          "foo": { "const": "bar" }
        },
        "required": ["foo"]
      }
    },
    { "required": ["bar"] }
  ]
}

"Foo" "bar" a eşit değilse, #/anyOf/0eşleşir ve doğrulama başarılı olur. "Foo" "bar" a eşitse, #/anyOf/0başarısız olur ve doğrulamanın başarılı #/anyOf/1olması için geçerli olması gerekir anyOf.

Sıralama

Koşulunuz bir enum'a dayanıyorsa, biraz daha basittir. "foo", "bar" veya "baz" olabilir. "Foo" "bar" a eşitse, "bar" gereklidir. "Foo" "baz" a eşitse, "baz" gereklidir.

{
  "type": "object",
  "properties": {
    "foo": { "enum": ["bar", "baz"] },
    "bar": { "type": "string" },
    "baz": { "type": "string" }
  },
  "anyOf": [
    {
      "properties": {
        "foo": { "const": "bar" }
      },
      "required": ["bar"]
    },
    {
      "properties": {
        "foo": { "const": "baz" }
      },
      "required": ["baz"]
    }
  ]
}

If-Then-Else

JSON Şemasına nispeten yeni bir ekleme (taslak-07)if , thenve elseanahtar kelimelerini ekler . "Foo" özelliği "bar" a eşitse, "bar" özelliği gerekir

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "if": {
    "properties": {
      "foo": { "const": "bar" }
    },
    "required": ["foo"]
  },
  "then": { "required": ["bar"] }
}

DÜZENLEME 12/23/2017: Uygulama bölümü güncellendi ve If-Then-Else bölümü eklendi.

DÜZENLEME 06/04/2018: If-Then-Else için hata düzeltmesi enumve kullanmak için tekilleri güncelleme const.


7
@scubbo if-then-elseAnahtar kelimelerin hayranı değilim ve onları kullanmayı reddediyorum. Ancak, kullanmayı seçerseniz, her zaman allOfyalnızca bu üç anahtar kelimeyi içeren bir şekilde sarmalamanızı öneririm . { ...other_keywords..., "allOf": [{ "if": ..., "then": ..., "else": ... }], ...more_keywords... }
Jason Desrosiers

2
@Jason Neden hayranı değilsin if...? Cevabınızda bununla ilgili kısa bir görüşün tamamen haklı olacağını düşünüyorum. Yoksa uzun bir hikaye mi?
Clay Bridges

7
@ClayBridges Yorum bölümü bu tartışma için doğru yer değil, ama işte kısa versiyon. Genel bir kural olarak, JSON Şeması anahtar kelimeleri durumsuzdur. Örneği doğrulamak için anahtar kelime değerinden başka hiçbir Bilgi kullanılamaz. if, thenve elsebirbirlerine bağlı oldukları için bu kuralı ihlal ederler.
Jason Desrosiers

3
@Girard, bu kalıpların JSON Schema'da kullanımının bildiğim en iyi tedavisi. Boole işlemleri resmi olarak belgelenmiştir, ancak geri kalanı sadece matematiktir. allOf== VE, anyOf== VEYA, oneOf== ÖZELVEYA ve not== DEĞİL. Matematikle ilgili daha fazla kaynak (örneğin, çıkarım) için google "boole cebri" ni kullanabilirsiniz.
Jason Desrosiers

2
@AlexeyShrub Bir süredir bunun hakkında yazmak istiyordum ama başka şeyler dikkatimi dağıttı. Koşullu fikrinin hayranıyım . İnsanların anlamasını kolaylaştırır. Benim itirazım, üç ayrı durum bilgili anahtar kelime olarak tanımlanma şeklidir (önceki yoruma bakınız). Diğer anahtar kelimelerin izlediği mimari özellikleri ihlal eden anahtar kelimelere sahip olmak, JSON Şeması doğrulayıcılarının uygulanmasını zorlaştırır ve daha az verimli hale getirir. Koşullar, devletsiz farklı bir şekilde tanımlansaydı, o zaman itirazım olmazdı.
Jason Desrosiers
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.