Faktury i rachunki mają to samo wejście. Jak uniknąć mieszania obu struktur?
W jednym interfejsie odbierane są zarówno faktury, jak i paragony, a pisanie dużych obiektów jest łatwe, gdy „wszystkie pola są opcjonalne”. Taki przedmiot może pomieścić wszystko, ale trudno powiedzieć, co dokładnie jest odbierane. Bardziej przejrzystym byłoby zachowanie dwóch oddzielnych umów i wybranie jednej z nich z jawnym polem typu.
Faktury i rachunki są często umieszczane w tym samym interfejsie w celu ich przetwarzania, ale jeśli do ich otrzymania zostanie użyty tylko szeroki obiekt z „wszystkimi polami opcjonalnymi", może on pomieścić dowolne dane wejściowe, ale nie będzie w stanie stwierdzić, jakiego rodzaju dokument został otrzymany. Ten artykuł jest przeznaczony dla programistów i personelu biznesowego, którzy muszą zaprojektować interfejs odbierania dokumentów lub utrzymywać reguły sprawdzania poprawności schematu JSON. Po przeczytaniu tego dowiesz się, jak zachować dwie niezależne umowy, wybrać jedną z jawnym polem typu oraz radzić sobie z konfliktami gałęzi i nieznanymi typami.
W przykładach w tym artykule wykorzystano próbki syntetyczne w celu zademonstrowania metod przetwarzania. Kod został sprawdzony na przykładach w izolowanym środowisku, ale nie gwarantuje to działania wszystkich rzeczywistych plików ani produktu. Przed przystąpieniem do przetwarzania ważnych dokumentów prosimy o zachowanie oryginałów i zapoznanie się z nimi zgodnie z granicami i pozycjami akceptacji w tekście.
Jak sobie poradzić ze wspólnym wprowadzaniem faktur i paragonów? Wniosek w jednym zdaniu
W przypadku otrzymania dwóch dokumentów z tego samego portalu wygodniej jest zachować dwie oddzielne umowy i wybrać jedną z nich za pomocą wymaganego polakind, zamiast używać szerokiego obiektu, w którym zmieści się wszystko.
| twoja sytuacja | Zalecane praktyki | powód |
|---|---|---|
| Ten sam interfejs musi odbierać faktury i paragony | Zachowaj dwie oddzielne umowy, wybrane za pomocą wymaganego pola rodzaju | Duży obiekt z opcjonalnymi wszystkimi polami może pomieścić wszystko, ale trudno wyjaśnić, co jest odbierane. |
| Organizuj oddziały za pomocą oneOf | Każda gałąź używa const do ustalenia rodzaju | oneOf wymaga dopasowania dokładnie jednej gałęzi. Nakładające się pola gałęzi spowodują niepowodzenie poprawnego wprowadzania danych. |
| Wprowadź brakujący typ lub konflikt pól | Zwróć wyraźny komunikat o błędzie pokazujący sprzeczne pola i źródła | Samo wyświetlenie komunikatu „brak dopasowania"nie może pomóc w zlokalizowaniu problemu |
| Klasyfikator nie potrafi rozróżnić typów dokumentów | Zachowaj status nieznany i wejdź do niezależnej kolejki do klasyfikacji | Losowy wybór oddziału przyniesie jedynie fałszywy „sukces" |
| Weryfikacja konstrukcji zaliczona | Nie oznacza to, że klasyfikacja jest prawidłowa ani że dokumenty są autentyczne. | Pewność klasyfikacji, weryfikacja struktury i autentyczność biznesowa to trzy różne poziomy |
Dlaczego nie możesz użyć szerokiego obiektu?
Ryzyko, że wszystkie pola staną się opcjonalne
Gdy interfejs akceptuje zarówno faktury, jak i paragony, łatwo jest pisać duże obiekty, korzystając z opcji „wszystkie pola opcjonalne". Taki obiekt może rzeczywiście otrzymywać różnorodne dane wejściowe, ale kosztem:
- Ze struktury nie można stwierdzić, który dokument został otrzymany.
- Pozycje wymagane i opcjonalne obu dokumentów są ze sobą pomieszane, a zasady weryfikacji stają się coraz bardziej niejasne.
- Kiedy pojawia się błąd, trudno jest dokładnie wyjaśnić, gdzie dane wejściowe nie są zgodne z oczekiwaniami.
Bardziej przejrzystym byłoby zachowanie dwóch oddzielnych umów i wybranie jednej z nich z wyraźnym polem typu.
oneOf nie jest byle jakim
Nakładające się gałęzie spowodują niepowodzenie wprowadzania poprawnych danych.
oneOf wymaga, aby dane wejściowe odpowiadały dokładnie jednej gałęzi. Jeśli obie gałęzie przejdą pomyślnie w tym samym czasie, ogólna weryfikacja zakończy się niepowodzeniem.
Jeśli gałęzie zawierają tylko kilka opcjonalnych pól, prawdopodobnie w znacznym stopniu będą się na siebie nakładać. W tej chwili legalne dane wejściowe nie przechodzą weryfikacji.
Użyj rodzaju i stałej, aby wyeliminować nakładanie się
Użycie wymaganego pola kind plus stałej wartości const może ustalić wyraźne granice pomiędzy gałęziami i z wyprzedzeniem wyeliminować takie nakładanie się.
Więcej szczegółów na temat zasad kombinacji można znaleźć w Reguły kombinacji schematu JSON.
Wykonywalny protokół odciążający
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"})
Jest to uproszczony przykładowy rekord i nie stanowi pełnego modelu polowego prawdziwej faktury. Kod demonstruje wybór gałęzi i odrzucanie zbędnych pól. Stawkę podatku, nagłówek i kwotę należy określić osobno.
Jeśli firma dopuszcza dodatkowe pola, przestrzenie nazw dla tych pól powinny być wyraźnie określone, a nie po cichu anulować wszystkie ograniczenia.
Nie wyświetlaj po prostu „brak dopasowania"w komunikacie o błędzie
Wyświetlana jest tylko „niezgodność"i ani użytkownicy, ani opiekunowie nie wiedzą, gdzie leży problem. W poniższej tabeli wymieniono kilka typowych funkcji wejściowych i odpowiadające im metody przesyłania informacji zwrotnych:
| Funkcje wejściowe | Rzeczywiste wątpliwości | Sugestie i opinie |
|---|---|---|
| rodzaju brakuje | Nie można wybrać protokołu | Proszę podać typ dokumentu |
| Typ koliduje z polem liczbowym | Obie struktury są mieszane | Pokaż sprzeczne pola i źródła |
| Numer pusty ciąg | Klucz istnieje, ale nie ma wartości | Spójrz ponownie na ponumerowany obszar |
| nieznany typ | Nieobjęte obecną umową | Wejdź do niezależnej kolejki oczekujących |
Nieokreślone typy również potrzebują ujścia
Jeśli klasyfikator nie jest w stanie rozróżnić faktur i paragonów, powinien pozostawić nieznany stan, zamiast wybierać losową gałąź w celu odgadnięcia „sukcesu".
Istnieją trzy różne poziomy, które należy rozpatrywać oddzielnie:
- Poufność klasyfikacji: Jak pewny jest system w ocenie typu dokumentu.
- Weryfikacja struktury: Czy dane wejściowe są zgodne z wybraną umową.
- Autentyczność biznesowa: Czy sam dokument jest autentyczny i ważny.
Przejście weryfikacji strukturalnej nie może udowodnić prawidłowości klasyfikacji ani autentyczności dokumentu.
Typ dokumentu również musi zostać zachowany w procesie tłumaczenia
W tym samym polu może być konieczne użycie różnych terminów w różnych dokumentach. W przypadku korzystania z terminologii OmniDoc i dwujęzycznych przepływów pracy recenzji podanie typu dokumentu wraz z listą dostaw pomaga recenzentom zrozumieć kontekst liczb i kwot.
Nie pozwól, aby szeroki obiekt JSON wymazał te różnice.
📊 Porównanie rdzeni
| praktyka | Czy możesz określić typ dokumentu? | Zachowanie, gdy gałęzie zachodzą na siebie | Obsługa nieznanych typów |
|---|---|---|---|
| Szeroki obiekt ze wszystkimi polami opcjonalnymi | Trudno opisać to, co otrzymałem. | Nie dotyczy, brak granic gałęzi pomiędzy polami | Łatwo połknięty przez szeroką gamę obiektów i trudny do wykrycia |
| Dwie niezależne umowy + wymagany rodzaj | Jawny wybór poprzez pole rodzaju | Użyj const, aby naprawić wartość i zmniejszyć nakładanie się | Zachowaj status nieznany i wejdź do kolejki do klasyfikacji |
🎯 Która metoda jest dla Ciebie odpowiednia?
Jeśli chcesz otrzymywać zarówno faktury, jak i rachunki
Zachowaj dwie oddzielne umowy i ustaw kind jako pole wymagane.
Jeśli pola oddziałów często się pokrywają
Napraw kind za pomocą const w każdej gałęzi, aby uniknąć dopasowania prawidłowych danych wejściowych do wielu gałęzi jednocześnie.
Jeśli Twój system pozwala na dodatkowe pola
Najpierw wyjaśnij przestrzeń nazw dodatkowych pól, a następnie zdecyduj, jak złagodzić ograniczenia.
Jeśli Twój klasyfikator nie jest wystarczająco pewny
Pozostaw status nieznany, wyślij dokument do kolejki do posortowania i nie wybieraj na siłę oddziału.
❓ Często zadawane pytania (FAQ)
1. Dlaczego po prostu nie użyć obiektu, w którym wszystkie pola są opcjonalne?
Taki przedmiot może pomieścić wszystko, ale trudno powiedzieć, co dokładnie jest odbierane.
2. Dlaczego oneOf nie wprowadza prawidłowych danych?
oneOf wymaga dopasowania dokładnie jednej gałęzi. Jeśli obie gałęzie przejdą pomyślnie w tym samym czasie, ogólna weryfikacja zakończy się niepowodzeniem. Taka sytuacja może łatwo wystąpić, gdy pola gałęzi w dużym stopniu nakładają się na siebie.
3. Na co należy zwrócić uwagę dopuszczając dodatkowe pola?
Przestrzeń nazw dodatkowych pól powinna być wyraźnie określona, a nie dyskretnie anulować wszystkie ograniczenia.
4. Co zrobić, jeśli klasyfikator nie jest w stanie określić typu dokumentu?
Zachowaj stan nieznany i wejdź do niezależnej kolejki do klasyfikacji. Nie wybieraj losowo oddziału, aby osiągnąć sukces.
5. Czy pozytywny wynik weryfikacji konstrukcji oznacza, że dokument jest autentyczny?
nie mogę. Pewność klasyfikacji, weryfikacja struktury i autentyczność biznesowa to trzy różne poziomy. Przejście przez obiekt nie może udowodnić autentyczności dokumentu.
📝 Podsumowanie
Umieszczając faktury i paragony w tym samym zapisie należy zachować dwie osobne umowy i zaznaczyć je z wymaganym polem kind tak, aby rodzaj wprowadzanego dokumentu był wyraźnie widoczny. Weryfikację oddziałów, informację zwrotną o błędach i wyjścia nieznanego typu należy również projektować wspólnie.
Wypróbuj teraz: prześlij dokument, aby rozpocząć tłumaczenie, zachowując oryginalny układ


