thuộc tính jsonSchema bắt buộc có điều kiện


97

Trong jsonSchema, bạn có thể cho biết các trường đã xác định là bắt buộc hay không bằng cách sử dụng requiredthuộc tính:

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

Trong một số trường hợp nhất định, tôi không muốn messageVersionlĩnh vực này là bắt buộc. Có cách nào để làm cho điều kiện bắt buộc của trường này không?


Có, nó sẽ có thể. Thông tin nào trong dữ liệu sẽ kích hoạt yêu cầu bắt buộc?
jruizaranguren

@SarveswaranMeenakshiSundaram - Tôi không biết tôi đã v4 chỉ đã qua sử dụng của giản đồ json
tom Redfern

Điều này có thể xảy ra trong phiên bản 3 không?
Sarvesh

@SarveswaranMeenakshiSundaram - Tôi không biết. Hãy thử nó và cho chúng tôi biết xin vui lòng!
tom redfern

Câu trả lời:


264

Tùy thuộc vào tình huống của bạn, có một vài cách tiếp cận khác nhau. Tôi có thể nghĩ ra bốn cách khác nhau để yêu cầu một trường có điều kiện.

Sự phụ thuộc

Các dependenciestừ khóa là một biến thể có điều kiện của các requiredtừ khóa. Báo trước thuộc tính trong dependencies, nếu thuộc tính có trong JSON đang được xác thực, thì lược đồ được liên kết với khóa đó cũng phải hợp lệ. Nếu có thuộc tính "foo", thì thuộc tính "bar" là bắt buộc

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

Cũng có một dạng rút gọn nếu lược đồ chỉ chứa requiredtừ khóa.

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

Hàm ý

Nếu điều kiện của bạn phụ thuộc vào giá trị của một trường, bạn có thể sử dụng khái niệm logic boolean được gọi là hàm ý. "A ngụ ý B" có nghĩa là, nếu A đúng thì B cũng phải đúng. Hàm ý cũng có thể được diễn đạt là "! A hoặc B". Thuộc tính "foo" không bằng "bar" hoặc thuộc tính "bar" là bắt buộc . Hay nói cách khác: Nếu thuộc tính "foo" bằng "bar", thì thuộc tính "bar" là bắt buộc

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

Nếu "foo" không bằng "bar", #/anyOf/0kết quả khớp và xác thực sẽ thành công. Nếu "foo" bằng "bar", #/anyOf/0không thành công và #/anyOf/1phải có giá trị để anyOfxác thực thành công.

Enum

Nếu điều kiện của bạn dựa trên enum, thì sẽ dễ dàng hơn một chút. "foo" có thể là "bar" hoặc "baz". Nếu "foo" bằng "bar", thì "bar" là bắt buộc. Nếu "foo" bằng "baz", thì "baz" là bắt buộc.

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

Nếu-Thì-Khác

Một sự bổ sung tương đối mới để JSON Schema (draft-07) cho biết thêm if, thenelsetừ khóa. Nếu thuộc tính "foo" bằng "bar", thì thuộc tính "bar" là bắt buộc

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

CHỈNH SỬA 23/12/2017: Đã cập nhật phần hàm ý và thêm phần If-Then-Else.

CHỈNH SỬA 06/04/2018: Sửa lỗi cho If-Then-Else và cập nhật singleton enums để sử dụng const.


7
@scubbo Tôi không phải là người yêu thích các if-then-elsetừ khóa và tôi từ chối sử dụng chúng. Nhưng, nếu bạn chọn sử dụng nó, tôi khuyên bạn nên luôn gói chúng trong một allOfchỉ chứa ba từ khóa đó. { ...other_keywords..., "allOf": [{ "if": ..., "then": ..., "else": ... }], ...more_keywords... }
Jason Desrosiers

2
@Jason Tại sao không phải là một fan hâm mộ của if...? Tôi nghĩ rằng một ý kiến ​​ngắn gọn về điều này trong câu trả lời của bạn sẽ hoàn toàn hợp lý. Hay là một câu chuyện dài?
Cầu đất sét

6
@ClayBridges Phần bình luận không phải là nơi thích hợp cho cuộc thảo luận đó, nhưng đây là phiên bản ngắn. Theo quy tắc chung, các từ khóa của Lược đồ JSON là không trạng thái. Không có Thông tin nào khác ngoài giá trị từ khóa có thể được sử dụng để xác thực phiên bản. if, thenelsevi phạm quy tắc này vì chúng phụ thuộc vào nhau.
Jason Desrosiers

3
@GGirard, đây là cách xử lý tốt nhất về việc sử dụng các mẫu này trong Lược đồ JSON mà tôi biết. Các phép toán boolean được chính thức ghi lại nhưng phần còn lại chỉ là toán học. allOf== VÀ, anyOf== HOẶC, oneOf== XOR và not== KHÔNG. Bạn có thể google "đại số boolean" để biết thêm tài nguyên về các công cụ toán học (chẳng hạn như hàm ý).
Jason Desrosiers

2
@AlexeyShrub Tôi đã muốn viết về điều này một thời gian, nhưng đã bị phân tâm bởi những thứ khác. Tôi là một fan hâm mộ của ý tưởng về một điều kiện. Nó làm cho mọi người dễ hiểu hơn. Sự phản đối của tôi là cách nó được định nghĩa như ba từ khóa trạng thái riêng biệt (xem bình luận trước). Việc có các từ khóa vi phạm các thuộc tính kiến ​​trúc mà các từ khóa khác tuân theo khiến trình xác thực Lược đồ JSON khó triển khai hơn và kém hiệu quả hơn. Nếu các điều kiện được định nghĩa theo một cách khác không có trạng thái, thì tôi sẽ không phản đối.
Jason Desrosiers
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.