Sinh JSON Schema từ dữ liệu mẫu: quy tắc suy kiểu và những chỗ phải sửa tay
Công cụ đọc một đoạn JSON mẫu rồi dựng ra bộ khung JSON Schema theo draft-07: suy kiểu cho từng trường, tách integer với number, nhận diện chuỗi dạng email, đường dẫn và mốc thời gian. Kết quả là bản nháp để bạn bổ sung ràng buộc, không phải schema hoàn chỉnh dùng ngay cho môi trường thật.
Tính năng nổi bật
- Sinh schema theo draft-07, tự gắn sẵn trường $schema trỏ về đúng bản đặc tả
- Suy kiểu đệ quy cho object và array lồng nhau, không giới hạn độ sâu
- Tách số nguyên thành integer và số có phần thập phân thành number
- Nhận diện ba dạng chuỗi thường gặp và gắn format là email, uri hoặc date-time
- Đưa toàn bộ khóa của mỗi object vào mảng required để bạn bớt đi những cái không cần
- Nút nạp dữ liệu mẫu chứa đủ các kiểu để bạn xem nhanh cách công cụ ánh xạ
- Báo lỗi ngay khi JSON dán vào sai cú pháp, không sinh ra schema sai lệch
- Nút sao chép toàn bộ schema đã định dạng thụt lề hai khoảng trắng
- Chạy hoàn toàn trong trình duyệt, dữ liệu bạn dán không rời khỏi máy
Vì sao nên bắt đầu bằng schema sinh tự động thay vì gõ từ đầu
Viết JSON Schema bằng tay cho một payload có ba tầng lồng nhau là công việc vừa dài vừa dễ sót. Chỉ riêng phần khai báo kiểu và liệt kê khóa đã chiếm phần lớn số dòng, mà đó lại là phần máy làm chính xác hơn người: máy không gõ nhầm tên khóa, không quên một trường nằm sâu trong mảng, không lẫn giữa integer và number. Cách làm hiệu quả là để máy dựng khung rồi bạn dành thời gian cho phần thật sự cần suy nghĩ, tức là các ràng buộc nghiệp vụ: trường nào được phép vắng, chuỗi nào phải khớp mẫu, số nào có khoảng giá trị hợp lệ, trường trạng thái nhận đúng những giá trị nào. Cần nhớ một điều quan trọng: schema sinh ra chỉ phản ánh đúng mẫu bạn dán vào. Nếu mẫu đó là một bản ghi may mắn có đủ mọi trường, schema sẽ bắt buộc mọi trường, và nó sẽ chặn nhầm những bản ghi hợp lệ khác.
Lợi ích khi sử dụng
- Bỏ qua phần gõ tay dài nhất là khai báo kiểu và liệt kê khóa lồng nhau
- Có ngay một bản nháp đúng cú pháp để đưa vào bộ kiểm tra mà không sợ lỗi định dạng
- Nhìn thấy cấu trúc thật của payload, tiện khi tiếp nhận API do người khác viết
- Dùng làm điểm khởi đầu để sinh kiểu TypeScript hoặc dữ liệu giả cho kiểm thử
- Xử lý cục bộ nên dán được cả payload có dữ liệu nội bộ mà không lo lộ ra ngoài
Cách sinh JSON Schema từ dữ liệu mẫu
- 1Dán một bản ghi JSON tiêu biểu vào ô bên trái, hoặc bấm nút Mẫu để nạp dữ liệu ví dụ có đủ các kiểu.
- 2Chọn bản ghi có nhiều trường nhất và mảng có phần tử đại diện nhất, vì công cụ chỉ nhìn đúng những gì bạn đưa vào.
- 3Bấm Tạo Schema, nếu ô báo JSON không hợp lệ thì kiểm tra dấu phẩy thừa, dấu nháy đơn hoặc chú thích lẫn trong dữ liệu.
- 4Đọc schema ở ô bên phải và cắt bớt mảng required cho những trường có thể vắng mặt trong thực tế.
- 5Bổ sung ràng buộc cần thiết như minLength, pattern, enum, minimum rồi sao chép sang dự án hoặc tài liệu mô tả API.
Công cụ suy kiểu theo đúng những quy tắc nào
Giá trị null cho ra kiểu null. Số được kiểm tra bằng phép thử số nguyên: 30 thành integer, còn 30.5 thành number. Lưu ý một cái bẫy của JSON là 30.0 khi phân tích cú pháp vẫn là số nguyên, nên một trường tiền tệ có giá trị chẵn trong mẫu sẽ bị gắn nhầm thành integer. Giá trị đúng sai cho ra boolean. Chuỗi được đối chiếu với ba mẫu theo thứ tự: bắt đầu bằng bốn chữ số, dấu gạch nối, hai chữ số, dấu gạch nối, hai chữ số thì gắn format date-time; chứa một ký tự a còng ngăn giữa hai phần và có dấu chấm ở phần sau thì gắn format email; bắt đầu bằng http hoặc https thì gắn format uri; còn lại là chuỗi trơn. Với object, công cụ duyệt mọi cặp khóa giá trị, dựng nhánh properties và đẩy toàn bộ khóa vào mảng required. Với mảng, nếu rỗng thì items để trống, còn có phần tử thì lấy đúng phần tử đầu tiên làm khuôn cho toàn mảng.
Bốn chỗ gần như luôn phải sửa tay sau khi sinh
Thứ nhất là mảng required. Công cụ đưa hết mọi khóa vào đó vì từ một bản ghi nó không có cách nào biết trường nào tùy chọn. Hãy bỏ khỏi required những trường có thể vắng, nếu không bộ kiểm tra sẽ chặn dữ liệu hợp lệ. Thứ hai là trường nhận null. Một trường có giá trị null trong mẫu sẽ ra kiểu null thuần, tức là chỉ chấp nhận đúng null và từ chối giá trị thật; hãy đổi thành mảng hai kiểu, ví dụ kiểu ghi là chuỗi hoặc null. Thứ ba là mảng không đồng nhất. Vì chỉ phần tử đầu được lấy làm khuôn, một mảng chứa nhiều dạng phần tử sẽ sinh schema chặn mất phần còn lại; cách sửa là dùng anyOf trong items. Thứ tư là chuỗi ngày. Một giá trị chỉ có ngày như 2024-01-15 vẫn bị gắn date-time, trong khi đúng ra phải là format date; giữ nguyên sẽ khiến bộ kiểm tra báo lỗi ở dữ liệu hợp lệ.
Bổ sung ràng buộc để schema thật sự chặn được dữ liệu xấu
Bộ khung sinh ra mới chỉ kiểm tra kiểu, còn phần lớn lỗi dữ liệu trong thực tế lại là lỗi giá trị. Với chuỗi, thêm minLength và maxLength cho các trường có giới hạn độ dài như số điện thoại hay mã đơn hàng, thêm pattern kèm biểu thức chính quy cho định dạng cố định, thêm enum cho trường trạng thái chỉ nhận vài giá trị. Với số, thêm minimum và maximum cho khoảng hợp lệ, dùng exclusiveMinimum khi cần loại bỏ chính giá trị biên, dùng multipleOf khi giá trị phải là bội của một đơn vị. Với mảng, thêm minItems và maxItems, thêm uniqueItems khi không cho phép trùng. Với object, thêm additionalProperties đặt là false nếu muốn từ chối những khóa lạ, đây là cách bắt sớm lỗi gõ nhầm tên trường. Cuối cùng, khi cùng một cấu trúc lặp ở nhiều nhánh, hãy tách vào definitions rồi tham chiếu bằng $ref để sửa một chỗ áp dụng mọi nơi.
Các bản đặc tả và vì sao công cụ chọn draft-07
JSON Schema không đánh số phiên bản theo kiểu thông thường mà theo các bản nháp. Draft-04 là bản cũ, viết required kiểu khác và dùng exclusiveMinimum như một giá trị đúng sai. Draft-06 thêm const, contains và propertyNames. Draft-07 bổ sung nhóm if, then, else cho kiểm tra có điều kiện, cùng readOnly và writeOnly. Draft-2019-09 đưa vào $defs thay cho definitions, thêm dependentRequired và unevaluatedProperties. Draft-2020-12 đổi cách mô tả mảng có vị trí cố định sang prefixItems và là bản mà đặc tả OpenAPI 3.1 dùng lại nguyên vẹn. Công cụ này xuất draft-07 vì đây vẫn là bản có mức hỗ trợ rộng nhất trong các thư viện kiểm tra thực tế. Nếu hệ thống của bạn theo OpenAPI 3.0, lưu ý bản đó dùng một nhánh riêng gần với draft-04 và không hiểu mọi từ khóa của draft-07, nên cần đối chiếu lại trước khi dán schema vào.
Đưa schema vào việc: kiểm tra, sinh kiểu và dựng dữ liệu giả
Ở phía JavaScript, thư viện phổ biến nhất là Ajv. Có một điểm hay khiến người mới bối rối: từ khóa format trong draft-07 mang tính chú thích, Ajv mặc định không kiểm tra nó, phải cài thêm gói ajv-formats và đăng ký thì email hay uri mới thật sự được xác thực. Ở phía Python có thư viện jsonschema, muốn kiểm tra format cũng phải bật bộ kiểm tra định dạng riêng. Ngoài kiểm tra, schema còn dùng để sinh mã: json-schema-to-typescript và quicktype đổi schema thành interface TypeScript, nhờ đó kiểu ở phía giao diện luôn khớp với hợp đồng dữ liệu thay vì gõ lại bằng tay. Chiều ngược lại, json-schema-faker sinh dữ liệu ngẫu nhiên hợp lệ theo schema, rất tiện để dựng phản hồi giả cho kiểm thử. Trong tài liệu API, dán schema vào phần components rồi tham chiếu lại giúp mỗi lần đổi cấu trúc chỉ phải sửa một chỗ.
Câu hỏi thường gặp (FAQ)
JSON Schema dùng để làm gì trong dự án thật?
Nó là bản mô tả cấu trúc dữ liệu đọc được bằng máy, dùng để kiểm tra payload gửi lên hoặc trả về có đúng khuôn hay không trước khi xử lý. Ngoài kiểm tra, cùng một schema còn dùng để sinh kiểu cho ngôn ngữ lập trình, dựng tài liệu API và tạo dữ liệu giả cho kiểm thử, nhờ đó nhiều bên cùng bám vào một nguồn duy nhất.
Vì sao mọi trường đều bị đưa vào required?
Vì công cụ chỉ nhìn thấy một bản ghi mẫu và trong bản ghi đó trường nào cũng có mặt, nên nó không có căn cứ nào để đoán trường nào được phép vắng. Đây là chỗ bạn phải can thiệp: giữ lại trong required những trường thật sự bắt buộc theo nghiệp vụ và xóa phần còn lại, nếu không bộ kiểm tra sẽ từ chối dữ liệu hợp lệ.
Mảng có nhiều kiểu phần tử khác nhau thì schema có đúng không?
Không đúng. Công cụ lấy phần tử đầu tiên làm khuôn cho toàn mảng, nên nếu phần tử thứ hai có cấu trúc khác thì nó sẽ bị coi là không hợp lệ. Cách sửa là thay nhánh items bằng anyOf liệt kê từng dạng phần tử. Với mảng mà mỗi vị trí có kiểu riêng, hãy dùng dạng mảng cho items ở draft-07 hoặc prefixItems ở bản 2020-12.
Trường có giá trị null trong mẫu thì xử lý thế nào?
Công cụ sinh ra kiểu null thuần, nghĩa là trường đó chỉ chấp nhận đúng giá trị null và sẽ báo lỗi khi nhận chuỗi hay số thật. Bạn nên sửa thành mảng hai kiểu, ví dụ khai báo kiểu là chuỗi hoặc null, hoặc bọc trong anyOf. Cách tốt hơn nữa là dán một bản ghi mẫu mà trường đó có giá trị thật rồi tự thêm null vào sau.
Vì sao trường chỉ chứa ngày lại bị gắn format date-time?
Vì bộ nhận diện chỉ kiểm tra phần đầu chuỗi có dạng bốn chữ số, gạch nối, hai chữ số, gạch nối, hai chữ số, nên cả 2024-01-15 lẫn 2024-01-15T10:30:00Z đều rơi vào cùng một nhánh. Nếu dữ liệu của bạn chỉ có ngày, hãy sửa format thành date, vì bộ kiểm tra hiểu date-time là phải có đủ phần giờ theo chuẩn thời gian quốc tế.
Số 30.0 vì sao lại thành integer thay vì number?
Vì JSON không phân biệt số nguyên với số thực, sau khi phân tích cú pháp thì 30.0 và 30 là cùng một giá trị và phép thử số nguyên trả về đúng. Với các trường tiền tệ hay tỷ lệ, hãy chủ động sửa thành number, nếu không một giá trị lẻ như 30.5 xuất hiện sau này sẽ bị bộ kiểm tra từ chối.
Thêm ràng buộc độ dài, khoảng giá trị hay danh sách giá trị cố định bằng cách nào?
Sau khi sao chép schema, bạn thêm minLength và maxLength vào nhánh chuỗi, minimum và maximum vào nhánh số, enum kèm danh sách giá trị vào trường trạng thái, pattern kèm biểu thức chính quy cho định dạng cố định. Với object, đặt additionalProperties bằng false để từ chối khóa lạ. Đây là phần công cụ không đoán được vì nó thuộc về quy tắc nghiệp vụ.
Vì sao Ajv không báo lỗi khi email sai định dạng?
Trong draft-07, từ khóa format mặc định chỉ mang tính chú thích chứ không bắt buộc bộ kiểm tra phải xác thực. Ajv tách phần này ra gói riêng, bạn cần cài ajv-formats rồi đăng ký với thực thể Ajv thì email, uri và date-time mới thật sự được kiểm tra. Thư viện jsonschema của Python cũng cần bật bộ kiểm tra định dạng tương tự.
Schema này dán thẳng vào tài liệu OpenAPI được không?
Với OpenAPI 3.1 thì được, vì bản đó dùng lại JSON Schema bản 2020-12 và tương thích ngược tốt với các từ khóa cơ bản của draft-07. Với OpenAPI 3.0 thì cần rà lại, vì bản đó dựa trên một nhánh gần draft-04, dùng nullable riêng thay cho mảng kiểu và không hiểu một số từ khóa mới hơn.
Có cách nào sinh schema từ nhiều bản ghi cùng lúc không?
Công cụ này đọc đúng một tài liệu JSON mỗi lần. Một mẹo hữu ích là gói nhiều bản ghi vào một mảng rồi dán vào, tuy nhiên vì chỉ phần tử đầu được dùng làm khuôn nên bạn vẫn phải tự hợp nhất bằng tay. Cách thực tế hơn là chọn bản ghi đầy đủ trường nhất làm gốc rồi đối chiếu thêm với vài bản ghi khác để chỉnh required.
Dán JSON có chú thích hoặc dấu phẩy cuối thì sao?
Công cụ sẽ báo JSON không hợp lệ, vì nó dùng bộ phân tích cú pháp JSON chuẩn và chuẩn này không cho phép chú thích lẫn dấu phẩy sau phần tử cuối. Những biến thể như JSON5 hay JSONC chấp nhận các thứ đó nhưng không phải JSON thuần. Hãy bỏ chú thích và dấu phẩy thừa, đồng thời đổi nháy đơn thành nháy kép trước khi dán.
Dữ liệu tôi dán vào có được gửi lên máy chủ không?
Không. Việc phân tích cú pháp và suy kiểu đều chạy bằng JavaScript trong trình duyệt của bạn, không có lượt gọi mạng nào khi bấm tạo schema. Bạn có thể tự kiểm chứng bằng tab Network trong công cụ dành cho nhà phát triển. Dù vậy, với payload chứa dữ liệu khách hàng thật, thói quen an toàn vẫn là thay giá trị thật bằng giá trị giả trước khi dán.
Từ khóa liên quan
- json schema generator
- tạo json schema online
- sinh json schema từ json
- json schema draft 07
- json schema là gì
- validate json bằng schema
- json to schema online
- json schema required
- json schema additionalproperties
- json schema pattern regex
- ajv validate json schema
- ajv formats email
- json schema to typescript
- quicktype json schema
- json schema faker dữ liệu giả
- openapi schema components
- json schema ref definitions
- json schema nullable
- kiểm tra dữ liệu api request body
- công cụ json schema miễn phí
