Obecnie koduję API dla sieci społecznościowej za pomocą Slim Framework. Moje pytanie brzmi: jakie są najlepsze praktyki, gdy nie ma wierszy do zwrócenia w strukturze json?
Powiedzmy, że to wywołanie / v1 / get / movies zwraca 2 wiersze od tabeli nazw filmów:
[
{"name": "Ghostbusters"},
{"name": "Indiana Jones"}
]
Ale potem wywołuję / v1 / get / books i nie ma żadnych wierszy w tej tabeli. Czy powinienem po prostu zwrócić pustą strukturę?
[
]
... czy byłby to lepszy komunikat i kod błędu?
[
"errors": {
"message": "no matches found",
"code": 134
}
]
Która jest lepsza praktyka? (interfejs API będzie używany w aplikacjach na iOS i Androida) Dzięki!
programming-practices
rest
api-design
json
Andres SK
źródło
źródło
[{"name": "..."}, {"name":"..."}]
Odpowiedzi:
Zwykle zwracam w wyniku liczbę rekordów jako metadane. Nie jestem pewien, czy jest to normalna praktyka REST, ale nie jest to wiele dodatkowych danych i jest bardzo precyzyjna. Zazwyczaj istnieje wiele stronicowania dla wielu usług, niepraktyczne jest zwracanie ogromnego zestawu wyników naraz. Osobiście denerwuje mnie podział na małe zestawy wyników. Jeśli jest pusty, wróć
number_of_records : 0
i książki jako pusta lista / tablicabooks : []
.EDYCJA (kilka lat później): Odpowiedź Martina Wickmana jest znacznie lepsza, oto „krótkie” wyjaśnienie dlaczego.
W przypadku paginacji należy zawsze pamiętać o możliwości zmiany treści lub zamówienia. Np. Przychodzi pierwsze zapytanie, 24 wyniki, zwracane jest pierwsze 10. Następnie dodaje się „nową książkę”, a teraz masz 25 wyników, ale z oryginalnym żądaniem zostałoby zamówione na 10 miejscu. Gdy pierwszy użytkownik zażąda drugiej strony, nie dostanie „nowej książki”. Istnieją sposoby radzenia sobie z takimi problemami, takie jak podanie „id żądania”, który powinien zostać wysłany z następującymi wywołaniami API, a następnie zwrócenie następnej strony ze „starego” zestawu wyników, który należy jakoś zapisać i powiązać z „id żądania”. Alternatywą jest dodanie pola typu „lista wyników zmieniona od pierwszego żądania”.
Zasadniczo, jeśli możesz, spróbuj włożyć dodatkowy wysiłek i unikaj paginacji. Podział na strony to dodatkowy stan, który można mutować, a śledzenie takich zmian jest podatne na błędy, tym bardziej, że zarówno serwer, jak i klient muszą sobie z tym poradzić.
Jeśli masz za dużo danych do przetworzenia na raz , rozważ zwrócenie „listy identyfikatorów” ze wszystkimi wynikami i szczegółami dla części tej listy i podaj wywołania API multi_get / get_by_id_list API dla zasobów.
źródło
books
parametr jest obiektem, ale „książki” implikują więcej niż jeden, a więcej niż jeden implikuje tablicę. Metadane są fajne i ostatecznie spodziewam się, że zbiór książek będzie tablicą obiektów książkowych; jeśli nie ma książek, daj mi pustą tablicęTwój przykład jest zepsuty. Nie powinieneś mieć obiektów Json ze zduplikowanymi kluczami. To, czego szukasz, to tablica z obiektami filmowymi, takimi jak to:
To podejście również odpowiada na twoje pytanie. Powinieneś zwrócić pustą tablicę, gdy zapytanie nie pasuje:
Z drugiej strony, jeśli spróbujesz uzyskać konkretny zasób filmu,
GET api/movie/34
a ten film nie istnieje, zwróć 404 z odpowiednim komunikatem o błędzie (zakodowanym w formacie json) w treściźródło
json_xs
.Jeśli jest to JSON, naprawdę powinieneś rozważyć zwrócenie tablicy obiektów. Ma to wiele zalet, w tym to, że gdy nie masz żadnych rekordów, jest to pusta tablica.
Więc kiedy masz rekordy, powrócisz:
A jeśli nie masz żadnych zapisów, powrócisz:
źródło
Jeśli operacja zostanie wykonana pomyślnie, ale nie ma nic do zwrócenia, na przykład pusta mapa
{}
lub pusta tablica[]
Wolałbym odpowiedzieć kodem odpowiedzi 204, oto fragment specyfikacji Definicje kodów stanu HTTP :Zasadniczo zalecam używanie 204 w aplikacjach RESTful przez HTTP, gdy nie ma nic do zwrócenia.
źródło
Sporo pracy wykonano przy tworzeniu znormalizowanego formatu API JSON .
Przestrzeganie zasad zawartych w tej specyfikacji oznacza, że wszystkie zwracane zasoby powinny być skutecznie „kolekcjami” (nawet jeśli uwzględniony jest tylko jeden zasób). Postępowanie w ten sposób oznaczałoby, że Twoje wezwanie do
/v1/get/movies
powrotu:Twoje wezwanie do
/v1/get/books
(które zwraca zero zasobów) zwróci:źródło
W twoim konkretnym przykładzie zaleciłbym, aby / v1 / get / books zwrócił HTTP 200 z pustą tablicą.
Jeśli dobrze czytam Twój post, Twój interfejs API zamierza zbierać książki. Mówiąc metaforycznie, masz półkę na książki, stojak na filmy DVD i ewentualnie inne pojemniki, o których tu nie wspomniałeś. Ponieważ zamierzasz zbierać książki, / v1 / get / books to twoja półka na książki. Oznacza to, że istnieje tam ważny zasób - lista książek - które w twoim przykładzie są puste.
Powodem, dla którego nie sugeruję zwracania HTTP 404 w tym przypadku jest to, że półka wciąż tam jest. W tej chwili nie ma na nim żadnych książek, ale nadal jest to półka na książki. Jeśli nie byłby to półka z książkami - jeśli API nie zamierzał na przykład zbierać książek - wtedy HTTP 404 byłby odpowiedni. Ale ponieważ istnieje tam zasób, nie powinieneś sygnalizować, że nie ma takiego zasobu, co robi HTTP 404. Dlatego twierdzę, że 200 z pustą tablicą (oznaczającą kolekcję) jest bardziej odpowiednie.
Powodem, dla którego nie sugeruję zwracania HTTP 204, jest to, że sugerowałoby to, że „Brak treści” jest zwykłym stanem rzeczy: wykonanie tej akcji na tym zasobie zwykle niczego nie zwróci. Dlatego jest zwykle używany jako odpowiedź na żądania DELETE, na przykład: charakter usunięcia ogólnie oznacza, że nie ma nic do zwrócenia. Sprawa jest podobna, gdy jest używana do odpowiadania na żądania za pomocą rodziny nagłówków If-Modified: chciałeś treści tylko, jeśli zasób się zmienił, ale nie zmienił się, więc nie dam ci żadnej treści.
Twierdzę jednak, że dla POBIERANIA pustej, ale poprawnej kolekcji, HTTP 204 nie ma sensu. Jeśli w kolekcji znajdują się elementy, poprawną reprezentacją będzie tablica tych danych. Dlatego, gdy nie ma tam żadnych danych (ale kolekcja jest poprawna), poprawną reprezentacją jest pusta tablica.
źródło
Naprawdę powinieneś zrobić tylko jedną z dwóch rzeczy
Albo Zwróć
200 (OK)
kod stanu i pustą tablicę w treści.Lub Zwróć
204 (NO CONTENT)
kod stanu i BRAK odpowiedzi.Dla mnie opcja 2 wydaje się bardziej poprawna technicznie i zgodna z zasadami REST i HTTP.
Jednak opcja 1 wydaje się bardziej wydajna dla klienta - ponieważ klient nie potrzebuje dodatkowej logiki, aby rozróżnić dwa (statusowe) kody stanu. Ponieważ wie, że zawsze otrzyma tablicę, musi po prostu sprawdzić, czy nie dostał żadnego, jednego lub wielu elementów i odpowiednio go przetworzyć
źródło
Widziałem oba przypadki w środowiskach produkcyjnych. Wybór zależy od tego, kto będzie korzystał z interfejsu API. Jeśli chcą wiedzieć, dlaczego lista jest pusta lub mieć pewność, że lista jest naprawdę pusta i podczas jej pobierania nie wystąpiły żadne błędy, należy dołączyć obiekt „error”. Jeśli ich to nie obchodzi, zwróć pustą listę. Wybrałbym drugie podejście, ponieważ obejmuje ono więcej potrzeb niż pierwsze.
źródło
Pierwszą rzeczą do rozważenia, ponieważ budujesz interfejs API RESTful, jest zwrócenie odpowiedniego kodu odpowiedzi. Bardziej odpowiednim kodem odpowiedzi do komunikowania się, że żądanie przebiegło normalnie, ale żądany zasób nie jest w tej chwili dostępny, jest czcigodny 404.
Jeśli projektujesz interfejs API w taki sposób, aby zawsze zwracał rozsądny kod odpowiedzi, być może nawet nie będziesz musiał zwracać treści, gdy nie znaleziono zasobu. To powiedziawszy, zwrócenie ciała, szczególnie ludzkiego, nie może zranić.
Nie ma tu „najlepszej praktyki”, oba przykłady są arbitralne, wystarczy wybrać jedną i zachować spójność . Programiści nienawidzą niespodzianek. Jeśli
/v1/get/movies
powróci,{}
gdy nie będzie filmów, spodziewamy/v1/get/actors
się powrotu,{}
gdy nie będzie aktorów.źródło
Nie wydaje mi się, żeby odpowiedź była ścisła.
Odpowiedź udzielona przez nirth powinna być najlepsza, w prawdziwym scenariuszu REST. Odpowiedź ciała powinna być pusta, a kod stanu http: 204; zasób istnieje, ale w tym czasie nie ma „treści”: jest pusty.
REST HTTP_Status_Codes
źródło
Polecam ponad 200 pustych tablic, ponieważ upraszcza to obsługę wszystkich klientów interfejsu API. Tablica 200+ oznacza „Zwróciłem wszystkie dane, które tam są”. Zarówno w przypadku kodu dostarczającego dane, jak i kodu przetwarzającego je liczba elementów byłaby nieistotna.
Każdy inny kod stanu musi być odpowiednio udokumentowany i prawidłowo dostarczony przez serwer i odpowiednio przetworzony przez klienta, a wszyscy wiemy, jak prawdopodobne jest to zdarzenie.
Sugerowano zwrócenie statusu 204 + puste ciało. Oznacza to, że zmuszają każdego pojedynczego klienta do stanu procesu 204 poprawnie. Ponadto zmuszasz ich do obsługi odpowiedzi innych niż JSON! Mam nadzieję, że wszyscy zdają sobie sprawę, że tylko dlatego, że żądanie otrzymało odpowiedź, nie oznacza to, że odpowiedź pochodzi z serwera, gdy używany jest protokół HTTP, a jedynie sprawdzenie, czy odpowiedź to JSON, obsługuje wiele z tych przypadków.
źródło
Chciałbym „To zależy”.
Jeśli zero jest rozsądnym wynikiem, zwróć pustą listę. Na przykład, jeśli chcesz, aby wszyscy pracownicy nazywali się „bob”, a „brak” to całkiem rozsądny wynik. Jeśli nie jest to oczekiwany wynik, zwróć błąd. Na przykład uzyskanie historycznej listy adresów dla osoby, którą zatrudniasz. Muszą oni gdzieś mieszkać, więc żaden wynik nie jest prawdopodobnie błędem, a nie zwykłym stanem.
Jestem pewien, że możesz spierać się ze specyfiką mojego przykładu, ale masz pomysł ...
źródło
get
adresu URL nie jest RESTful, metoda GET implikuje metodę HTTP.GET
api/movies
Zwróć a200 OK
z pustą tablicą[]
.GET
api/movies/1
(gdzie1
jest identyfikator) i nie istnieje, zwróć a404 Not Found
.Dlaczego? Żądasz zasobów . Gdy żądasz kolekcji, sam zasób (kolekcja) istnieje. Dlatego
404
jest źle. Ale jeśli poprosisz o konkretny film i nie istnieje, żądany zasób nie istnieje i musisz go zwrócić404
.źródło
Jeśli zwracasz JSON, lepiej zawsze zwracać liczbę i komunikat o błędzie i być może wartość logiczną wskazującą, czy wystąpił błąd, czy nie, to są moje trzy standardowe meta wartości zwracane z każdą listą wierszy.
źródło