+1

Validate data sử dụng Json schema (Phần 2)

Đây là bài viết tiếp theo của loạt bài viết về validate data sử dụng json schema. Có thể tham khảo Phần 1: Sử dụng Json Schema validate data

Trong bài viết này, chúng ta sẽ tìm hiểu những tùy chọn validate cho những dữ liệu cụ thể. Nhắc lại, trong json-schema, chúng ta có những kiểu dữ liệu sau:

  • Kiểu string
  • Kiểu number
  • Kiểu array
  • Kiểu object
  • Kiểu boolean
  • Kiểu null
  • Kiểu integer

Chúng ta sẽ đi tìm hiểu chi tiết những tùy chọn của từng kiểu một.

Validate kiểu dữ liệu string

  • Hai tùy chọn cơ bản của dữ liệu string này là: maxLengthminLength. Hai tùy chọn này quy định độ dài chuỗi ký tự của thuộc tính thông qua phương thức .length() của kiểu dữ liệu string. Ví dụ
var schema = { "maxLength": 2 };
 
var ajv = Ajv(); // count unicode pairs as one character
ajv.validate(schema, "😀😀"); // true
ajv.validate(schema, "😀😀!"); // false
 
var ajv = Ajv({unicode: false}); // count unicode pairs as two characters
ajv.validate(schema, "😀"); // true
ajv.validate(schema, "😀!"); // false
  • Ngoài ra, những tùy chọn khác cũng rất quan trọng của kiểu string là: formatpattern. format là từ khóa định nghĩa ý nghĩa của string theo định dạng một cách tiêu chuẩn. Có những định dạng bao gồm: email, date, date-time, ipv4, ipv6, hostname, uri. Ví dụ
var ajv = Ajv(); // "fast" format validation
ajv.validate({"format": "date"}, "2015-12-24"); // true
ajv.validate({"format": "date"}, "2015-14-33"); // true
 
var ajv = Ajv({format: 'full'); // more thorough format validation
ajv.validate({"format": "date"}, "2015-12-24"); // true
ajv.validate({"format": "date"}, "2015-14-33"); // false

pattern là từ khóa chỉ sử dụng cho việc validate dữ liệu kiểu string. Nó được sử dụng mang theo ý nghĩa thông thường, không khác gì so với javascript hay ý nghĩa thường gặp ở các trường hợp khác. Nó mang ý nghĩa cơ bản của việc định nghĩa chuỗi string đầu vào đúng với chuỗi regex được định dạng. Ví dụ:

{"pattern": "^[1-9][0-9]*$" };   /^[1-9][0-9]*$/;  // id
{"pattern": "^[A-Za-z]+$" };     /^[a-z]+$/i;      // letters
{"pattern": "^[0-9()\\-\\.\\s]+$"}; /^[0-9()\-\.\s]+$/; // phone
  • Một điều được cho là sự tiến bộ và linh hoạt khi sử dụng Json-schema để validate dữ liệu string là ta có thể tự định nghĩa một kiểu và sử dụng nó với từ khóa format giống như các định dạng email, date, date-time.v.v được nêu ra ở trên. Cụ thể:
ajv.addFormat('phone', /^[0-9()\-\.\s]+$/);
{ "type": "string", "format": "phone" }

Validate dữ liệu kiểu number

  • 4 tùy chọn cơ bản của kiểu dữ liệu number là : minimum, maximum, exclusiveMinimum, exclusiveMaximum. Ý nghĩa của những từ khóa này đúng theo ý nghĩa của chúng tương ứng với: giá trị nhỏ nhất, giá trị lớn nhất, giá trị nghiêm ngặt nhỏ nhất, giá trị nghiêm ngặt lớn nhất. Có thể gía trị nghiêm ngặt hơi khó hiểu, nhưng nó đúng (hoặc gần đúng) với ý nghĩa của chúng trong toán học mà chúng ta đề cập ở đây. Để dễ hiểu hơn chúng ta sẽ đi qua ví dụ
{
  "type": "integer",
  "minimum": 13,
  "exclusiveMinimum": true
}

trong ví dụ trên, thì giá trị nhỏ nhất là 13 và vì exclusiveMinimumtrue nên giá trị thỏa mãn json-schema định nghĩa phải là một giá trị lớn hơn giá trị 13. Trong trường hợp ngược lại của thuộc tính exclusiveMinimum (exclusiveMinimum: false) thì giá trị có thể nhận nhỏ nhất là 13. Tương tự với quan hệ giữa hai từ khóa maximumexclusiveMaximum. Vì là một tùy chọn khi validate dữ liệu kiểu number, chúng ta có thể sử dụng đồng thời cả 4 tùy chọn minimum, maximum, exclusiveMinimum, exclusiveMaximum, hoặc sử dụng một từng phần tùy chọn riêng sao cho phù hợp với mục đích của mình.

  • Ngoài 4 tùy chọn cơ bản, chúng ta có một tùy chọn khác cũng thú vị đó là : multipleOf. Như ý nghĩa thể hiện, nó sẽ là bội số của một cái gì đó. Ví dụ
{ "multipleOf": 2.5 }

Thì dữ liệu khả dụng là : 2.5, 5, 7.5, bất kỳ một non-number ("abc", [], {}, null, true), dữ liệu không khả dụng có thể là : 2, 3, .v.v.

Validate dữ liệu boolean, null

  • Về mặt cơ bản, booleannull là hai kiểu dữ liệu không có tùy chọn. boolean nhận 2 giá trị true, false, null chỉ nhận gía trị null. Khi kiểu dữ liệu của một thuộc tính của Json-schema được định nghĩa là kiểu boolean hoặc null thì điều quan trọng nhất là thuộc tính ấy có được required hay không(hiểu nôm na là có phải bắt buộc phải có hay không). Ví dụ
{
    properties: {
       aProperty:  {
          "type": "boolean"
        }
    },
    required: ["aProperty"]
}

Trong ví dụ trên, thì thuộc tính aProperty bắt buộc phải có trong dữ liệu đầu vào, trong một trường hợp khác

{
    properties: {
       aProperty:  {
          "type": "boolean"
        }
    },
    required: []
}

thì không bắt buộc phải có aProperty

Validate dữ liệu kiểu array

  • Array là môt kiểu dữ liệu thường gặp, được định nghĩa trong mọi ngôn ngữ lập trình. Nó cũng được xem là một trong những kiểu dữ liệu gần với những kiểu dữ liệu nguyên thủy nhất.
  • Các tùy chọn quan trọng khi validate dữ liệu kiểu array là: maxItems , minItems, additionalItems, nó sử dụng cơ bản quy định số lượng phần tử (item) có trong mảng, hiểu đơn giản, nếu coi chuỗi là mảng các ký tự, thì ý nghĩa của maxItems, minItems tương tự với minLength, maxLength khi ta vaidate dữ liệu string. Điều khác biệt ở đây là với kiểu dữ liệu string, các thành phần là các là các ký tự thì ở kiểu mảng, các thành phần có thể là bất kỳ kiểu dữ liệu tiêu chuẩn nào được sử dụng bởi json-schema. Trong khi đó từ khóa additionalItems được sử dụng khi có nhiều hơn một kiểu dữ liệu trong các thành phần các phần tử của mảng. Thông thường, chúng ta thường có một mảng các phần tử cũng kiểu, như kiểu các số tự nhiên lớn hơn 2 và nhỏ hơn 6 ([3,4,5]), tuy nhiên, trong nhiều trường hợp, mảng có thể chưa các phần tử nhiều hơn một kiểu cơ bản. Trong trường hợp đó, additionalItems được coi là giải pháp để đưa thêm các kiểu có thể có trong mảng.
  • Chúng ta sẽ làm rõ ràng hơn thông qua 2 ví dụ sau
var schema = {
  "type": "array",
  "items": [
    { "type": "integer" },
    { "type": "string" }
  ],
  "additionalItems": false
};
 
var validate = ajv.compile(schema);
console.log(validate([1, "foo", 3])); // false
var schema = {
  "type": "array",
  "items": [
    { "type": "integer" },
    { "type": "string" }
  ],
  "additionalItems": { "type": "integer" }
};
 
var validate = ajv.compile(schema);
console.log(validate([1, "foo", 3])); // true
console.log(validate([1, "foo", 3, 4])); // true
console.log(validate([1, "foo", "bar"])); // false

Như vậy, thứ tự định nghĩa kiểu dữ liệu của mảng mang tính nhạy cảm nhé. Sử dụng từ nhạy cảm có tính chất tương tự với tính nhạy cảm trong phân biệt chữ hoa chữ thường trong một số ngôn ngữ lập trình.

Validate dữ liệu kiểu object.

  • Kiểu dữ liệu object là kiểu dữ liệu mang tính chung nhất, không phải là một kiểu dữ liệu nguyên thủy hay gần nguyên thủy, nhưng khá là quen thuộc khi các bạn có kiến thức về lập trình hướng đối tượng.
  • Những tùy chọn quan trọng của kiểu object bao gồm : “properties”, “required”, “additionalProperties”, “patternProperties”, “maxProperties”, “minProperties”, “dependencies”
  • Ngoài propertiesrequired là hai từ khóa khá lạ, các từ khóa còn lại đều tương tự hoặc mang ý nghĩa gần giống với những từ khóa được định nghĩa trong các kiểu nguyên thủy mà đã được nêu ở trên. Tuy nhiên, điểm khác biệt ở đây là trong khi các kiểu dữ liệu nguyên thủy hoặc gần nguyên thủy định nghĩa các thành phần theo một cách tự nhiên thì object là kiểu dữ liệu chú trọng đến việc định nghĩa các thành phần, các thuộc tính của nó trong Json-schema thông qua khóa properties. Từ khóa required sử dụng khi nhấn mạnh một thuộc tính của object là bắt buộc phải có có trong dữ liệu đầu vào. Trong khi các từ khóa additionalProperties, patternProperties, maxProperties, minProperties đều có thể suy ra từ những từ khóa anh em họ hàng xa của nó đã được nêu ở trên.
  • dependencies có lẽ là phức tạp nhất và khó hiểu và những từ khóa ít được sử dụng nhất, nhưng là một từ khóa rất mạnh mẽ cùng một lúc. Nó cho phép bạn xác định các yêu cầu mà các dữ liệu phải đáp ứng nếu nó có tính chất nhất định. Một số ví dụ validate kiểu object.
var schema = {
  "type": "object",
  "additionalProperties" {
    "type": "integer",
    "minimum": 0,
    "maximum": 65535
  }
};
var validate = ajv.compile(schema);
validate({a:1,b:10,c:100});    // true
validate({d:1,e:10,f:100000}); // false
validate({g:1,h:10,i:10.5});   // false
validate({j:1,k:10,l:'abc'});  // false

{
  "type": "object",
  "additionalProperties": { "type": "string" },
  "maxProperties": 6,
  "required": ["street", "postcode", "city", "country"]
}

{
  "properties": {
    "connType": { "enum": ["relative"] },
    "relation": { "type": "string" }
  },
  "dependencies": {
    "relation": ["close"]
  }
}

Tham khảo: Những từ khóa trong ajv


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí