Hóa đơn và biên lai có chung một lối vào. Làm thế nào để tránh trộn lẫn hai cấu trúc?

Một giao diện nhận cả hóa đơn và biên lai, đồng thời thật dễ dàng viết các đối tượng lớn với "tất cả các trường tùy chọn". Một vật thể như vậy có thể chứa bất cứ thứ gì, nhưng rất khó để biết chính xác nó được nhận là gì. Sẽ rõ ràng hơn nếu giữ hai hợp đồng riêng biệt và chọn một trong số chúng có trường loại rõ ràng.

Hóa đơn và biên lai thường được đưa vào cùng một giao diện để xử lý, nhưng nếu chỉ sử dụng một đối tượng rộng có "tất cả các trường tùy chọn" để nhận thì nó có thể chứa bất kỳ đầu vào nào, nhưng nó không thể cho biết loại tài liệu nào được nhận. Bài viết này dành cho các nhà phát triển và nhân viên kinh doanh cần thiết kế giao diện nhận tài liệu hoặc duy trì các quy tắc xác thực Lược đồ JSON. Sau khi đọc phần này, bạn sẽ tìm hiểu cách giữ hai hợp đồng độc lập, chọn một hợp đồng có trường loại rõ ràng và xử lý xung đột nhánh cũng như các loại không xác định.

Các ví dụ trong bài viết này sử dụng các mẫu tổng hợp để minh họa các phương pháp xử lý. Mã đã được kiểm tra bằng các ví dụ trong môi trường biệt lập, nhưng điều này không đảm bảo cho tất cả các tệp thực hoặc hiệu suất sản phẩm. Trước khi xử lý các văn bản quan trọng, vui lòng giữ lại bản chính và xem xét theo ranh giới và các mục chấp nhận trong văn bản.

Xử lý thế nào khi hóa đơn, biên lai bị nhập chung? Một câu kết luận

Khi nhận được hai tài liệu từ cùng một cổng, sẽ rõ ràng hơn nếu giữ hai hợp đồng riêng biệt và sử dụng trường kind bắt buộc để chọn một trong số chúng, thay vì sử dụng một đối tượng rộng có thể chứa mọi thứ.

hoàn cảnh của bạnCác phương pháp được đề xuấtlý do
Giao diện tương tự cần nhận hóa đơn, biên laiGiữ hai hợp đồng riêng biệt, được chọn với trường loại bắt buộcMột đối tượng lớn với tất cả các trường tùy chọn có thể chứa bất kỳ thứ gì, nhưng rất khó để giải thích những gì được nhận.
Tổ chức các nhánh với oneOfMỗi nhánh sử dụng const để sửa loạioneOf yêu cầu khớp chính xác một nhánh. Các trường nhánh chồng chéo sẽ khiến đầu vào hợp pháp không thành công.
Nhập thiếu loại hoặc xung đột trườngTrả về thông báo lỗi rõ ràng hiển thị các trường và nguồn xung độtChỉ hiển thị "không khớp" không thể giúp xác định vấn đề
Trình phân loại không thể phân biệt giữa các loại tài liệuGiữ lại trạng thái không xác định và vào hàng đợi độc lập để được phân loạiChọn ngẫu nhiên một nhánh sẽ chỉ tạo ra "thành công" giả
Xác minh cấu trúc đã được thông quaĐiều đó không có nghĩa là việc phân loại là chính xác, cũng không có nghĩa là các tài liệu đó là xác thực.Độ tin cậy phân loại, xác minh cấu trúc và tính xác thực của doanh nghiệp là ba cấp độ khác nhau

Tại sao bạn không thể sử dụng một đối tượng rộng?

Nguy cơ khiến tất cả các trường trở thành tùy chọn

Khi một giao diện chấp nhận cả hóa đơn và biên lai, bạn có thể dễ dàng viết các đối tượng lớn với "tất cả các trường tùy chọn". Một đối tượng như vậy thực sự có thể nhận được nhiều loại đầu vào khác nhau, nhưng với cái giá phải trả là:

  • Không thể biết từ cấu trúc tài liệu nào được nhận.
  • Các mục bắt buộc và mục tùy chọn của hai loại văn bản này bị trộn lẫn với nhau, quy định xác minh ngày càng mờ nhạt.
  • Khi xảy ra lỗi khó có thể giải thích chính xác đầu vào không như mong đợi ở đâu.

Sẽ rõ ràng hơn nếu giữ hai hợp đồng riêng biệt và chọn một trong số chúng có trường loại rõ ràng.

oneOf không phải là bất kỳ ai

Các nhánh chồng lấn có thể gây ra lỗi đầu vào hợp lệ

oneOf yêu cầu đầu vào phải khớp chính xác một nhánh. Nếu cả hai nhánh đều vượt qua đồng thời, việc xác thực tổng thể cũng sẽ thất bại.

Nếu một nhánh chỉ chứa một vài trường tùy chọn, chúng có khả năng chồng lấn rộng rãi. Ở thời điểm này, đầu vào hợp lệ thực sự không vượt qua được xác minh.

Sử dụng kind và const để loại bỏ sự chồng chéo

Bằng cách sử dụng trường kind cần thiết cộng với const để cố định giá trị, bạn có thể thiết lập ranh giới rõ ràng giữa các nhánh và loại bỏ sự chồng chéo này từ trước.

Để biết thêm chi tiết về các quy tắc kết hợp, hãy tham khảo Quy tắc kết hợp Lược đồ JSON.

Giao thức chuyển hướng thực thi

from jsonschema import Draft202012Validator

def branch(kind, identity):
    return {
        "type": "object", "additionalProperties": False,
        "required": ["kind", identity],
        "properties": {"kind": {"const": kind},
                       identity: {"type": "string", "minLength": 1}}
    }

schema = {"oneOf": [branch("invoice", "invoice_number"),
                    branch("receipt", "receipt_number")]}
v = Draft202012Validator(schema)
valid = lambda x: not list(v.iter_errors(x))
assert valid({"kind": "invoice", "invoice_number": "I-1"})
assert valid({"kind": "receipt", "receipt_number": "R-1"})
assert not valid({"kind": "invoice", "receipt_number": "R-1"})
assert not valid({"kind": "receipt", "receipt_number": ""})
assert not valid({"kind": "invoice", "invoice_number": "I-1",
                  "receipt_number": "R-1"})
assert not valid({"kind": "unknown"})

Đây là một bản ghi ví dụ được đơn giản hóa, không phải mô hình hoàn chỉnh của một hóa đơn thực tế. Mã cho thấy việc lựa chọn và từ chối các trường trùng lặp ở chi nhánh; mức thuế, tiêu đề và số tiền cần được định nghĩa riêng biệt.

Nếu doanh nghiệp cho phép các trường bổ sung, các không gian tên cho các trường này nên được xác định rõ ràng thay vì âm thầm loại bỏ tất cả các ràng buộc.

Đừng chỉ hiển thị thông báo lỗi "không khớp"

Chỉ hiển thị "không khớp", và cả người dùng lẫn nhân viên bảo trì đều không thể biết vấn đề nằm ở đâu. Bảng dưới đây liệt kê một số đặc điểm đầu vào phổ biến và các phương pháp phản hồi tương ứng của chúng:

Tính năng đầu vàoNhững nghi ngờ thực sựĐề xuất phản hồi
loại thiếu hụtKhông thể chọn thỏa thuậnVui lòng cung cấp loại tài liệu
Trường kiểu và số xung độtHai cấu trúc này được pha trộnHiển thị các trường xung đột và nguồn của chúng
Chuỗi rỗng được đánh sốChìa khóa tồn tại nhưng không có giá trịNhìn lại khu vực đánh số
Loại không xác địnhThỏa thuận hiện tại không bao gồm điều nàyNhập hàng đợi độc lập để được phân loại

Các loại không xác định cũng cần thoát

Nếu bộ phân loại không thể phân biệt hóa đơn và hóa đơn, trạng thái chưa xác định nên được giữ lại thay vì chọn ngẫu nhiên một nhánh để tạo ra "thành công."

Có ba cấp độ khác nhau ở đây cần được xem xét riêng biệt:

  • Độ tin cậy danh mục: Độ tin cậy của hệ thống trong việc đánh giá các loại tài liệu.
  • Xác minh cấu trúc: Nhập liệu hợp đồng đã chọn có được đáp ứng hay không.
  • Tính xác thực kinh doanh: Liệu các tài liệu có chính xác và hợp lệ hay không.

Việc xác minh cấu trúc không thể được chứng minh ngược lại là chính xác, cũng như không thể chứng minh tài liệu là thật.

Loại tài liệu cũng nên được giữ nguyên trong quá trình dịch

Cùng một lĩnh vực có thể yêu cầu thuật ngữ khác nhau trong các tài liệu khác nhau. Khi sử dụng thuật ngữ OmniDoc và quy trình đánh giá song ngữ, việc cung cấp các loại tài liệu với danh sách giao giúp người đánh giá hiểu được ngữ cảnh của số lượng và số lượng.

Đừng để một đối tượng JSON rộng lớn xóa đi những khác biệt này.

📊 So sánh cốt lõi

Phương phápLoại tài liệu có thể được xác định rõ ràng không?Biểu hiện khi các nhánh chồng lên nhauXử lý các loại không xác định
Các đối tượng rộng với tất cả các trường đều tùy chọnThật khó để diễn tả những gì đã nhận đượcKhông áp dụng; không có ranh giới nhánh giữa các trườngDễ dàng bị nuốt chửng bởi các mục tiêu rộng lớn và khó nhận ra
Hai hợp đồng độc lập + loại yêu cầuChọn rõ ràng bằng trường loạiSử dụng const để cố định giá trị nhằm giảm chồng lấnRời khỏi trạng thái chưa biết và vào hàng đợi để được sắp xếp

🎯 Phương pháp nào phù hợp với bạn?

Nếu bạn cần nhận cả hóa đơn và hóa đơn cùng lúc

Giữ hai hợp đồng riêng biệt và đặt kind làm trường bắt buộc.

Nếu các trường nhánh của bạn chồng lấn rộng rãi

Sửa kind với const trong mỗi nhánh để tránh đầu vào hợp lệ khớp nhiều nhánh cùng lúc.

Nếu hệ thống của bạn cho phép các trường bổ sung

Đầu tiên, làm rõ không gian tên của trường bổ sung, sau đó quyết định cách nới lỏng các ràng buộc.

Nếu bộ phân loại của bạn không đủ chắc chắn

Giữ trạng thái chưa xác định và gửi tài liệu vào hàng đợi để sắp xếp; không bắt buộc chọn nhánh.

❓ Câu hỏi thường gặp (FAQ)

1. Tại sao không dùng một đối tượng mà tất cả các trường đều là tùy chọn?

Một người bạn đời như vậy có thể giả vờ bất cứ điều gì, nhưng thật khó để biết chính xác họ nhận được gì.

2. Tại sao oneOf lại gây ra thất bại vào hợp lệ?

oneOf yêu cầu khớp chính xác một nhánh. Nếu cả hai nhánh đều vượt qua đồng thời, kiểm tra tổng thể sẽ thất bại. Tình huống này có khả năng xảy ra khi các trường nhánh chồng lấn rộng rãi.

3. Bạn nên chú ý điều gì khi cho phép các trường bổ sung?

Không gian tên cho trường bổ sung nên được xác định rõ ràng, thay vì âm thầm loại bỏ mọi ràng buộc.

4. Nếu bộ phân loại không thể xác định loại tài liệu thì sao?

Giữ trạng thái chưa biết và vào hàng đợi độc lập để được phân loại; không chọn ngẫu nhiên một nhánh để lắp ráp nhánh thành công.

5. Việc vượt qua xác minh cấu trúc có chứng minh tính xác thực của các tài liệu không?

Không. Độ tin cậy phân loại, xác minh cấu trúc và tính xác thực doanh nghiệp là ba cấp độ riêng biệt; xác minh cấu trúc không thể chứng minh tính xác thực của tài liệu.

📝 Tóm tắt

Khi đặt hóa đơn và biên lai vào cùng một mục, hãy giữ hai hợp đồng riêng biệt và chọn chúng bằng trường kind cần thiết, giúp loại tài liệu nhập trở nên rõ ràng. Xác minh nhánh, phản hồi lỗi và xuất loại không xác định cũng nên được thiết kế cùng nhau.

Trải nghiệm ngay: Tải lên tài liệu của bạn để bắt đầu dịch, giữ nguyên định dạng gốc

Cập nhật lúc 2026-11-15