Một hợp đồng JSON đang nhận địa chỉ giao hàng gồm mã tỉnh, mã khu vực và địa chỉ chi tiết. Nhóm tích hợp muốn dùng lại hợp đồng ấy cho khách doanh nghiệp rồi thêm mã bộ phận nhận hàng. Họ ghép một schema mới bằng allOf, nhưng bản JSON có đủ thông tin lại bị từ chối vì chứa trường bổ sung. Xóa trường ấy thì qua được phần cũ nhưng không còn đáp ứng phần mới.
Đây là tình huống giả lập để giải thích mở rộng JSON Schema allOf khi schema nền đã đóng. Bài tập trung vào phép kết hợp schema và cách kiểm tương thích của validator, không hướng dẫn thay mapping API đang chạy. Không có dữ liệu khách hàng hay kết quả triển khai thực tế trong ví dụ.
Đọc lỗi như một phép giao điều kiện
Cách nghĩ “schema con kế thừa schema cha rồi thêm trường” dễ gây nhầm. Theo tài liệu về kết hợp JSON Schema, allOf yêu cầu dữ liệu thỏa từng subschema. Nó không phải phép kế thừa hướng đối tượng tự sửa các ràng buộc của schema nền. Một điều kiện cấm trường vẫn tồn tại sau khi được đặt vào tổ hợp.
Hãy gọi ba trường nền là A, B, C và trường mới là D, chỉ để nhìn cấu trúc thay vì bận tâm dữ liệu địa chỉ. Schema nền nhận A, B, C và từ chối thuộc tính ngoài danh sách. Schema mở rộng yêu cầu có D. Đối tượng A, B, C, D thỏa phần mở rộng nhưng vi phạm lệnh đóng ở phần nền. Đối tượng A, B, C vượt phần nền nhưng thiếu D. Kết quả không mâu thuẫn với cách validator làm việc; các điều kiện đã không cùng mô tả được đối tượng mà đội muốn nhận.
Điều cần sửa vì thế không phải giá trị D. Thử đổi mã bộ phận, thêm chuỗi rỗng hoặc gửi lại nhiều lần không làm thay đổi quan hệ logic này. Nhóm nên đọc đường dẫn lỗi tới đúng subschema và từ khóa gây từ chối. Chỉ nhìn dòng cuối “additional property” có thể khiến người tích hợp nhầm rằng bên gửi đã vi phạm hợp đồng nghiệp vụ, trong khi vấn đề nằm ở cách hợp đồng được tổ hợp.
Giữ nguyên bản JSON tối thiểu gây lỗi là việc hữu ích đầu tiên. Loại khỏi mẫu các trường không liên quan, dữ liệu cá nhân và toàn bộ lớp truyền tải. Nếu hiện tượng vẫn tái hiện với bốn trường giả, đội đã có một đối tượng nhỏ để cùng trao đổi. Bản tối thiểu này không thay bộ thử đầy đủ, nhưng giúp thảo luận chính xác hơn một ảnh chụp lỗi từ payload dài hàng nghìn dòng.

Ba hướng thiết kế có đánh đổi khác nhau
Đóng hợp đồng cuối thay vì đóng phần tái sử dụng
Một hướng là giữ phần nền dùng chung cho các ràng buộc ổn định, rồi đặt quyết định cho phép những thuộc tính nào ở lớp cuối. Cách này đòi hỏi đội biết rõ các chỗ đang dùng schema nền. Nếu bỏ ràng buộc đóng ở một phần được chia sẻ mà không rà consumer, có thể vô tình nới hợp đồng của luồng khác. Sửa cấu trúc nhỏ không đồng nghĩa phạm vi tác động nhỏ.
Đội có thể cần tách một phần tái sử dụng mới thay vì sửa trực tiếp phần cũ. Hợp đồng hiện hành vẫn giữ nguyên cho bên đang dùng; hợp đồng mới được phát hành với cấu trúc rõ hơn. Đánh đổi là thêm một phiên bản cần quản lý, nhưng đổi lại không bắt mọi consumer phải nâng cùng lúc chỉ vì một luồng có thêm mã bộ phận.
Khai báo đầy đủ ở nơi đóng schema
Hướng thứ hai là tập hợp rõ các thuộc tính được phép ở vị trí áp dụng quy tắc đóng. Cách này dễ giải thích khi số trường nhỏ và hợp đồng ít biến thể. Tuy nhiên, nếu các trường chung được khai báo ở nhiều chỗ, một lần đổi ràng buộc có thể bị bỏ sót tại bản sao. Đội cần chọn nguồn định nghĩa chuẩn và cách đối chiếu những phần lặp, thay vì sao chép thủ công rồi dựa vào trí nhớ.
Trước khi chọn, hãy hỏi ai chịu trách nhiệm cập nhật khi A đổi kiểu hoặc B trở thành bắt buộc. Nếu câu trả lời là “bên nào gặp lỗi thì sửa”, cấu trúc mới có thể giải quyết một payload hôm nay nhưng tăng rủi ro lệch hợp đồng về sau. Chi phí bảo trì không chỉ là số dòng schema, mà còn là số điểm cần đưa cùng một quyết định nghiệp vụ vào thực tế.
Dùng từ khóa phù hợp với dialect được hỗ trợ
Tài liệu về unevaluatedProperties trình bày cơ chế xét các thuộc tính đã được đánh giá qua subschema, từ draft 2019-09. Đây có thể là một lựa chọn cho bài toán đóng đối tượng sau khi kết hợp. Điều kiện đi kèm là validator và cấu hình thực dùng phải hỗ trợ dialect cùng các từ khóa liên quan.
Thêm một từ khóa mới vào file không chứng minh bộ kiểm hiện tại đã hiểu nó. Nhóm cần xác minh đúng tên thư viện, phiên bản và cách chọn dialect. Nếu hệ thống có nhiều điểm kiểm, chẳng hạn phía gateway và phía ứng dụng, phải xem từng điểm thay vì chỉ thử bằng một công cụ trực tuyến. Kết quả ở công cụ đó không tạo bằng chứng tương thích cho bản cài doanh nghiệp.
Một bộ fixture nhỏ phải phân biệt được các lựa chọn
Với trường hợp A, B, C và D, đừng chỉ thử bản dữ liệu mong muốn. Cần thêm bản thiếu D, bản có D sai kiểu, bản có một thuộc tính lạ E, cùng một bản thiếu trường nền bắt buộc. Các giá trị đều có thể là chuỗi giả ngắn. Mục đích là xác nhận hợp đồng mới nhận đúng phạm vi, không chỉ khiến một lỗi cụ thể biến mất.
Hãy ghi kỳ vọng cho mỗi fixture trước khi chạy. Ví dụ, A, B, C, D phải được nhận trong hợp đồng mở rộng; A, B, C, D, E phải bị từ chối nếu đội chọn hợp đồng đóng cuối. Việc E được chấp nhận không nhất thiết là lỗi trong mọi thiết kế, nhưng phải phù hợp quyết định đã chốt. Một kết quả “valid” thiếu kỳ vọng bên cạnh không đủ giúp người tiếp nhận biết đó là thành công hay nới lỏng ngoài ý muốn.
Giữ một bản dữ liệu hợp lệ theo hợp đồng cũ để xem consumer cũ có bị tác động không. Nếu hợp đồng mới bắt buộc D, cần nêu rõ ai phải gửi trường này và từ lúc nào. Không nên thay hợp đồng dùng chung bằng bản mới rồi tự điền D cho tất cả dữ liệu cũ chỉ nhằm vượt bộ kiểm. Khả năng tương thích phải được quyết định có chủ ý, không được tạo bằng giá trị giả.
Khi lưu kết quả, cần phân biệt lỗi schema không hợp lệ với dữ liệu không hợp schema. Hai loại này dẫn tới người xử lý khác nhau. Đội phát triển chịu trách nhiệm một tổ hợp ràng buộc không đúng ý; người gửi chỉ có thể sửa dữ liệu khi hợp đồng đã rõ. Gộp cả hai vào thông báo “vui lòng nhập đúng thông tin” vừa không giúp sửa lỗi vừa khiến người dùng lặp lại thao tác vô ích.
Thời gian xử lý cũng nên được kiểm với mẫu đại diện nếu schema tổ hợp nhiều tầng. Tuy vậy, không cần biến bài toán bốn trường thành một dự án benchmark phức tạp. Bắt đầu bằng tính đúng, sau đó dùng phạm vi dữ liệu và cấu trúc thực để đánh giá hiệu năng. Đừng báo một con số nhanh trên fixture tối thiểu như năng lực của mọi payload production.
Phát hành một hợp đồng mới cần giữ được đường lui
Một gói thay đổi gọn nên có file schema cũ và mới, dialect đã chọn, danh sách consumer chịu tác động và fixture với kỳ vọng. Kèm theo đó là lý do chọn hướng thiết kế: giữ consumer cũ, giảm khai báo lặp hoặc cần hỗ trợ trường có điều kiện. Người duyệt có thể đánh giá đánh đổi thay vì chỉ thấy một dòng khóa đã bị xóa để “sửa lỗi”.
Đội cần biết dữ liệu đang chờ sẽ được xét theo hợp đồng nào. Một payload được tạo trước lúc nâng phiên bản nhưng đến sau lúc chuyển đổi không nên âm thầm đổi nghĩa. Cách gắn phiên bản, cách chuyển tiếp và phạm vi xử lý lại phụ thuộc hệ thống thực. Đây là câu hỏi phải làm rõ khi bàn giao, không phải tính năng mà allOf tự giải quyết. Nếu thay đổi còn tác động kiểu, đơn vị hoặc consumer, cần rà thêm bảng hợp đồng trường khi API đổi dữ liệu.
Nếu phải quay lại, việc khôi phục file schema chưa chắc khôi phục được trạng thái nghiệp vụ đã ghi trong thời gian dùng hợp đồng mới. Vì vậy, hãy đặt cổng kiểm trước tác vụ có hậu quả và giữ dấu phiên bản của đối tượng đã qua cổng. Kiểm cấu trúc chỉ có giá trị khi bước dùng dữ liệu nhận đúng bản đã được kiểm, không phải một bản được sửa hoặc sinh lại sau đó.
Thành công của thay đổi là người tích hợp giải thích được vì sao từng fixture được nhận hoặc bị từ chối và consumer liên quan vẫn làm đúng việc. Nó không được đo bằng việc giảm mọi cảnh báo xuống bằng không. Với nhu cầu rà hợp đồng dữ liệu và tương thích giữa các hệ thống, Onter có thể trao đổi phạm vi khảo sát, thiết kế và nghiệm thu. Giá: Liên hệ. Nhận tư vấn & báo giá.

