jsonSchema แอตทริบิวต์ที่จำเป็นตามเงื่อนไข


104

ใน jsonSchema คุณสามารถระบุได้ว่าฟิลด์ที่กำหนดเป็นฟิลด์บังคับหรือไม่โดยใช้requiredแอตทริบิวต์:

{
    "$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"
    ]
}

ในบางกรณีฉันไม่ต้องการให้messageVersionฟิลด์นี้บังคับ มีวิธีใดบ้างที่จะทำให้ฟิลด์นี้เป็นเงื่อนไขบังคับ


ใช่มันควรจะเป็นไปได้ ข้อมูลใดในข้อมูลที่จะกระตุ้นให้เกิดการบังคับ
jruizaranguren

@SarveswaranMeenakshiSundaram - ฉันไม่รู้ว่าฉันใช้ v4 ของ json schema เท่านั้น
tom redfern

เป็นไปได้หรือไม่ในเวอร์ชัน 3
Sarvesh

@SarveswaranMeenakshiSundaram - ไม่รู้สิ โปรดลองและแจ้งให้เราทราบ!
tom redfern

คำตอบ:


277

มีแนวทางที่แตกต่างกันเล็กน้อยขึ้นอยู่กับสถานการณ์ของคุณ ฉันคิดได้สี่วิธีในการกำหนดฟิลด์ตามเงื่อนไข

การพึ่งพา

dependenciesคำหลักคือการเปลี่ยนแปลงเงื่อนไขของrequiredคำหลัก คุณสมบัติ Foreach ในdependenciesหากคุณสมบัติมีอยู่ใน JSON ที่กำลังตรวจสอบความถูกต้องสคีมาที่เชื่อมโยงกับคีย์นั้นจะต้องถูกต้องด้วย หากมีคุณสมบัติ "foo" แสดงว่าต้องมีคุณสมบัติ "bar"

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

นอกจากนี้ยังมีรูปแบบสั้น ๆ หากสคีมามีเฉพาะrequiredคำหลัก

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

นัย

ถ้าเงื่อนไขของคุณขึ้นอยู่กับค่าของเขตข้อมูลคุณสามารถใช้แนวคิดตรรกะบูลีนที่เรียกว่านัย "A หมายถึง B" หมายความว่าอย่างมีประสิทธิภาพถ้า A เป็นจริง B ก็ต้องเป็นจริงด้วย ความหมายยังสามารถแสดงเป็น "! A หรือ B" ทั้งคุณสมบัติ "foo" ไม่เท่ากับ "บาร์" หรือทรัพย์สิน "บาร์" เป็นสิ่งจำเป็น หรืออีกนัยหนึ่ง: ถ้าคุณสมบัติ "foo" เท่ากับ "bar" ก็ต้องระบุคุณสมบัติ "bar"

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

หาก "foo" ไม่เท่ากับ "bar" การ#/anyOf/0จับคู่และการตรวจสอบความถูกต้องจะสำเร็จ หาก "foo" เท่ากับ "bar" #/anyOf/0ล้มเหลวและ#/anyOf/1ต้องถูกต้องเพื่อให้การanyOfตรวจสอบความถูกต้องสำเร็จ

Enum

หากเงื่อนไขของคุณเป็นไปตาม enum ก็จะตรงไปตรงมาอีกเล็กน้อย "foo" อาจเป็น "bar" หรือ "baz" ก็ได้ ถ้า "foo" เท่ากับ "bar" ก็ต้องระบุ "bar" ถ้า "foo" เท่ากับ "baz" ก็ต้องระบุ "baz"

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

ถ้า - แล้ว - อื่น ๆ

นอกจากนี้ค่อนข้างใหม่JSON Schema (ร่าง-07)เพิ่มif, thenและelseคำหลัก ถ้าคุณสมบัติ "foo" เท่ากับ "bar" ก็ต้องระบุคุณสมบัติ "bar"

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

แก้ไข 12/23/2017:ส่วนการแสดงนัยได้รับการอัปเดตและเพิ่มส่วน If-Then-Else

แก้ไข 2018/06/04:แก้ไขข้อผิดพลาดสำหรับหาก-แล้ว-อื่น ๆ และการปรับปรุงเดี่ยวenumS constใช้


7
@scubbo ฉันไม่ใช่แฟนของif-then-elseคีย์เวิร์ดและฉันปฏิเสธที่จะใช้มัน แต่ถ้าคุณเลือกที่จะใช้ฉันขอแนะนำให้รวมคำเหล่านั้นไว้ในคำallOfที่มีเพียงสามคำหลักเท่านั้น { ...other_keywords..., "allOf": [{ "if": ..., "then": ..., "else": ... }], ...more_keywords... }
Jason Desrosiers

2
@ Jason ทำไมไม่เป็นแฟนของif...? ฉันคิดว่าความคิดเห็นสั้น ๆ เกี่ยวกับเรื่องนี้ในคำตอบของคุณน่าจะเป็นธรรม หรือเป็นเรื่องยาว?
Clay Bridges

7
@ClayBridges ส่วนความคิดเห็นไม่ใช่สถานที่ที่เหมาะสมสำหรับการสนทนานั้น แต่นี่เป็นเวอร์ชันสั้น ๆ ตามกฎทั่วไปคีย์เวิร์ดสคีมา JSON จะไม่มีสถานะ ไม่สามารถใช้ข้อมูลอื่นนอกเหนือจากค่าคีย์เวิร์ดเพื่อตรวจสอบอินสแตนซ์ได้ if, thenและelseละเมิดกฎนี้เพราะพวกเขาขึ้นอยู่กับแต่ละอื่น ๆ
Jason Desrosiers

3
@GGirard นี่คือวิธีที่ดีที่สุดสำหรับการใช้รูปแบบเหล่านี้ใน JSON Schema ที่ฉันรู้จัก การดำเนินการบูลีนได้รับการบันทึกอย่างเป็นทางการ แต่ส่วนที่เหลือเป็นเพียงคณิตศาสตร์ allOf== AND, anyOf== OR, oneOf== XOR และnot== NOT คุณสามารถ google "พีชคณิตบูลีน" เพื่อดูแหล่งข้อมูลเพิ่มเติมเกี่ยวกับคณิตศาสตร์ (เช่นการแสดงนัย)
Jason Desrosiers

2
@AlexeyShrub ฉันอยากจะเขียนเกี่ยวกับเรื่องนี้มาระยะหนึ่งแล้ว แต่ถูกรบกวนด้วยเรื่องอื่น ฉันเป็นแฟนของความคิดของเงื่อนไข ทำให้คนเข้าใจง่ายขึ้น การคัดค้านของฉันเป็นไปตามวิธีที่กำหนดเป็นคำหลักที่ระบุสถานะแยกกันสามคำ (ดูความคิดเห็นก่อนหน้า) การมีคีย์เวิร์ดที่ละเมิดคุณสมบัติทางสถาปัตยกรรมที่คีย์เวิร์ดอื่นตามมาทำให้เครื่องมือตรวจสอบสคีมา JSON ใช้งานได้ยากขึ้นและมีประสิทธิภาพน้อยลง ถ้าเงื่อนไขถูกกำหนดด้วยวิธีอื่นที่ไร้สัญชาติฉันก็จะไม่คัดค้าน
Jason Desrosiers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.