Czy istnieje jakiś standard dla formatu odpowiedzi JSON API?

Czy istnieją standardy lub najlepsze praktyki strukturyzowania odpowiedzi JSON z API? Oczywiście, DANE każdej aplikacji są inne, więc nie chodzi mi o to, ale raczej o "response boilerplate", jeśli wolisz. Przykład tego co mam na myśli:

Pomyślne zapytanie:

{
  "success": true,
  "payload": {
    /* Application-specific data would go here. */
  }
}

Nie powiodło się żądanie:

{
  "success": false,
  "payload": {
    /* Application-specific data would go here. */
  },
  "error": {
    "code": 123,
    "message": "An error occurred!"
  }
}
 753
Author: Anish B., 2012-10-09

15 answers

Tak, pojawiło się kilka standardów (choć pewne swobody w zakresie definicji standardu):

  1. JSON API - JSON API obejmuje tworzenie i aktualizowanie zasobów, a nie tylko odpowiedzi.
  2. JSend - proste i prawdopodobnie to, co już robisz.
  3. protokół OData JSON - bardzo skomplikowany.
  4. HAL - podobny do Odaty, ale mający być HATEOAS podobny.

Istnieją również API JSON formaty opisu:

 693
Author: Adam Gent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-15 18:22:34

Przewodnik Google JSON

Zwrot odpowiedzi sukcesudata

{
  "data": {
    "id": 1001,
    "name": "Wing"
  }
}

Zwrot odpowiedzi na błąd error

{
  "error": {
    "code": 404,
    "message": "ID not found"
  }
}

A jeśli twoim klientem jest JS, możesz użyć if ("error" in response) {}, aby sprawdzić, czy nie ma błędu.

 224
Author: Steely Wing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-01 22:03:49

Domyślam się, że standard defacto tak naprawdę nie pojawił się (i może nigdy). Ale bez względu na to, oto moje zdanie:

Pomyślne zapytanie:

{
  "status": "success",
  "data": {
    /* Application-specific data would go here. */
  },
  "message": null /* Or optional success message */
}

Nie powiodło się żądanie:

{
  "status": "error",
  "data": null, /* or optional error payload */
  "message": "Error xyz has occurred"
}

Korzyść: te same elementy najwyższego poziomu zarówno w przypadku sukcesu, jak i błędu

Wada: brak kodu błędu, ale jeśli chcesz, możesz zmienić status na kod (sukces lub porażka), - lub-możesz dodać kolejny element najwyższego poziomu o nazwie "code".

 146
Author: trungly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-24 17:47:19

Zakładając, że pytanie dotyczy projektu REST webservices, a dokładniej sukcesu/błędu.

Myślę, że są 3 różne rodzaje konstrukcji.

  1. Użyj tylko kod statusu HTTP, aby wskazać, czy wystąpił błąd i spróbuj ograniczyć się do standardowych (zwykle powinno wystarczyć).

    • plusy: jest to standard niezależny od Twojego api.
    • wady: mniej informacji o tym, co naprawdę się stało.
  2. Użycie HTTP Status + JSON body (nawet jeśli jest to błąd). Zdefiniuj jednolitą strukturę błędów (np. kod, wiadomość, powód, typ itp.) i użyj jej do błędów, jeśli zakończy się sukcesem, po prostu zwróć oczekiwaną odpowiedź json.

    • plusy: nadal standardowo, ponieważ używasz istniejących kodów statusu HTTP i zwracasz json opisujący błąd (podajesz więcej informacji o tym, co się stało).
    • wady: wyjście json będzie się różnić w zależności od tego, czy jest to błąd lub sukces.
  3. Zapomnij o statusie http (np: zawsze status 200), Zawsze używaj json i dodaj w katalogu głównym odpowiedzi boolean responseValid i obiekt błędu (kod,wiadomość,itp.), który zostanie wypełniony, jeśli jest to błąd, w przeciwnym razie pozostałe pola (sukces) zostaną wypełnione.

    • Plusy: klient zajmuje się tylko ciałem odpowiedzi, które jest ciągiem json i ignoruje status(?).

    • Wady: tym mniej standard.

Wybór należy do ciebie:)

W zależności od API wybrałbym 2 lub 3 (wolę 2 dla JSON rest API). Inną rzeczą, którą doświadczyłem w projektowaniu REST Api jest znaczenie dokumentacji dla każdego Zasobu (url): parametry, treść, odpowiedź, nagłówki itp + przykłady.

Polecam również użycie jersey (implementacja jax-rs) +genson (biblioteka java / JSON databinding). You only have to drop genson + jersey w classpath i json jest automatycznie obsługiwany.

EDIT:

  • Rozwiązanie 2 jest najtrudniejsze do wdrożenia, ale zaletą jest to, że można ładnie radzić sobie z wyjątkami i nie tylko błędy biznesowe, początkowy wysiłek jest ważniejszy, ale wygrywasz na dłuższą metę.

  • Rozwiązanie 3 jest łatwe do zaimplementowania zarówno po stronie serwera, jak i klienta, ale nie jest tak miłe, ponieważ będziesz musiał hermetyzować obiekty, które chcesz zwrócić w odpowiedzi obiekt zawierający również błąd responseValid +.

 93
Author: eugen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-24 04:56:32

The RFC 7807: Problem Details for HTTP API jest w tej chwili najbliższą rzeczą jaką mamy do oficjalnego standardu.

 25
Author: Berislav Lopac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-03 20:39:32

Nie będę tak arogancki, twierdząc, że jest to standard, więc użyję formy "wolę".

Preferuję zwięzłą odpowiedź(przy żądaniu listy / artykułów chcę mieć tablicę artykułów JSON).

W moich projektach używam HTTP do raportowania stanu, a 200 zwraca tylko ładunek.

400 zwraca komunikat o błędzie w request:

{"message" : "Missing parameter: 'param'"}

Return 404 jeśli model / kontroler / URI nie istnieje

Jeśli wystąpił błąd z obróbką po mojej stronie, wracam 501 z wiadomością:

{"message" : "Could not connect to data store."}

Z tego, co widziałem, sporo frameworków spoczynkowych ma tendencję do tego.

Uzasadnienie :

JSON ma być formatem payload , nie jest protokołem sesji. Cała idea verbose session-owskich ładunków pochodzi ze świata XML/SOAP i różnych błędnych wyborów, które stworzyły te nadęte projekty. Po tym, jak zdaliśmy sobie sprawę, że to był ogromny ból głowy, cały punkt REST / JSON było pocałować go, i przestrzegać HTTP. Nie wydaje mi się, aby w JSend było coś zdalnie standard, a zwłaszcza nie z bardziej wyrazistymi wśród nich. XHR zareaguje na odpowiedź HTTP, jeśli używasz jQuery dla AJAX (jak większość) można użyć try/catch oraz done()/fail() wywołania zwrotne do przechwytywania błędów. Nie widzę, w jaki sposób zamykanie raportów stanu w JSON jest bardziej przydatne niż to.

 21
Author: Bojan Markovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-16 05:40:25

Poniżej znajduje się format JSON, którego używa instagram

{
    "meta": {
         "error_type": "OAuthException",
         "code": 400,
         "error_message": "..."
    }
    "data": {
         ...
    },
    "pagination": {
         "next_url": "...",
         "next_max_id": "13872296"
    }
}
 19
Author: Muhammad Amin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-13 08:19:54

Jeśli to coś warte, robię to inaczej. Pomyślne wywołanie ma tylko obiekty JSON. Nie potrzebuję obiektu JSON wyższego poziomu, który zawiera pole success wskazujące true i pole payload, które ma obiekt JSON. Po prostu zwracam odpowiedni obiekt JSON z 200 lub cokolwiek jest odpowiednie w zakresie 200 dla statusu HTTP w nagłówku.

Jednak, jeśli jest błąd (coś z rodziny 400) zwracam dobrze uformowany obiekt błędu JSON. Na przykład, jeśli klient jest wysyłanie użytkownika z adresem e-mail i numerem telefonu, a jeden z nich jest zniekształcony (tzn. nie mogę wstawić go do bazy danych) zwrócę coś takiego:

{
  "description" : "Validation Failed"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Invalid phone number."
  } ],
}

Ważne jest to, że właściwość "field" musi pasować do pola JSON dokładnie, którego nie można zweryfikować. Dzięki temu klienci mogą dokładnie wiedzieć, co poszło nie tak z ich żądaniem. Również "wiadomość" znajduje się w ustawieniach regionalnych żądania. Jeśli oba "emailAddress" i "phoneNumber" były nieprawidłowe, to tablica" errors " będzie zawierać wpisy dla obu. 409 (konflikt) ciało odpowiedzi JSON może wyglądać tak:

{
  "description" : "Already Exists"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Phone number already exists for another user."
  } ],
}

Z kodem statusu HTTP i tym JSONEM Klient ma wszystko, czego potrzebuje, aby odpowiadać na błędy w deterministyczny sposób i nie tworzy nowego standardu błędu, który próbuje zastąpić kody statusu HTTP. Uwaga, występują one tylko dla zakresu błędów 400. Za wszystko w zakresie 200 Mogę zwrócić wszystko, co jest odpowiednie. Dla mnie często jest to obiekt podobny do JSON ale to nie ma tu znaczenia.

Jedyną rzeczą, o której myślałem, był numeryczny kod błędu w wpisach tablicy "errors" lub katalogu głównym samego obiektu JSON. Ale do tej pory nie potrzebowaliśmy jej.

 17
Author: robert_difalco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-28 18:45:46

Ich nie jest zgoda na rest api formatów odpowiedzi dużych gigantów oprogramowania-Google, Facebook, Twitter, Amazon i innych, choć wiele linków zostały podane w odpowiedzi powyżej, gdzie niektórzy ludzie próbowali ustandaryzować format odpowiedzi.

Ponieważ potrzeby API mogą się różnić, bardzo trudno jest przekonać wszystkich i zgodzić się na jakiś format. Jeśli masz miliony użytkowników korzystających z API, dlaczego chcesz zmienić format odpowiedzi?

Following is my take on format odpowiedzi inspirowany przez Google, Twitter, Amazon i niektóre posty w Internecie:

Https://github.com/adnan-kamili/rest-api-response-format

Plik Swagger:

Https://github.com/adnan-kamili/swagger-sample-template

 13
Author: adnan kamili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-02 09:13:05

Celem JSON jest to, że jest on całkowicie dynamiczny i elastyczny. Zgiń go do dowolnego kaprysu, ponieważ jest to tylko zestaw serializowanych obiektów i tablic JavaScript, zakorzenionych w jednym węźle.

To, jaki jest typ rootnode zależy od ciebie, co zawiera, zależy od ciebie, czy wyślesz metadane wraz z odpowiedzią, czy ustawisz typ mime na application/json, czy zostawisz go jako text/plain, zależy od ciebie (o ile wiesz, jak obsługiwać edge przypadki).

Zbuduj lekki schemat, który lubisz.
Osobiście odkryłem, że śledzenie analityczne i serwowanie mp3/ogg i serwowanie Galerii Obrazów oraz przesyłanie wiadomości tekstowych i pakietów sieciowych Do Gier online, a także posty na blogu i komentarze na blogu wszystkie mają bardzo różne wymagania pod względem tego, co jest wysyłane i co jest odbierane i jak powinny być spożywane.

Więc ostatnią rzeczą, jakiej bym chciała, robiąc to wszystko, jest próba dostosowania każdego z nich do ten sam standard kotła, który jest oparty na XML2. 0 lub somesuch.

To powiedziawszy, jest wiele do powiedzenia na temat używania schematów, które mają sens ty i są dobrze przemyślane.
Po prostu przeczytaj kilka odpowiedzi API, zanotuj, co lubisz, krytykuj to, czego nie lubisz, napisz te krytyczne uwagi i zrozum, dlaczego pocierają cię w niewłaściwy sposób, a następnie zastanów się, jak zastosować to, czego się nauczyłeś, do tego, czego potrzebujesz.

 7
Author: Norguard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-09 19:06:53

JSON-RPC 2.0 definiuje standardowy format żądania i odpowiedzi i jest powiewem świeżego powietrza po pracy z interfejsami API REST.

 7
Author: dnault,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-11 22:09:18

Sugerowany podstawowy framework wygląda dobrze, ale zdefiniowany obiekt błędu jest zbyt ograniczony. Często nie można użyć jednej wartości do wyrażenia problemu, a zamiast tego potrzebny jest łańcuch problemów i przyczyn .

Poszperałem trochę i odkryłem, że najczęstszym formatem zwracania błędów (wyjątków) jest struktura tej formy:

{
   "success": false,
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

Jest to format proponowany przez OASIS data standard Oasis OData i wydaje się być najbardziej standardową opcją tam jednak wydaje się, że nie ma na tym etapie wysokich wskaźników przyjęcia żadnej normy. Format ten jest zgodny ze specyfikacją JSON-RPC.

Kompletną bibliotekę open source, która to implementuje, można znaleźć pod adresem: Mendocino JSON Utilities . Ta biblioteka obsługuje obiekty JSON, jak również wyjątki.

Szczegóły są omówione w moim poście na blogu Obsługa błędów w JSON REST API

 4
Author: AgilePro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-04 00:52:25

Dla tych, którzy przyjdą później, oprócz zaakceptowanej odpowiedzi, która obejmuje HAL, JSend i JSON API, dodałbym kilka innych specyfikacji wartych przyjrzenia się:

  • JSON-LD jest rekomendacją W3C i określa, jak budować interoperacyjne Usługi internetowe w JSON.]}
  • W 1995 roku, w wyniku połączenia z JSON, powstała nowa wersja JSON-a, która została zastąpiona przez JSON-a, a w 1998 roku została zastąpiona przez JSON-a]}
 3
Author: A. Barakat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-06 15:45:27

Nie ma innego standardu łamania prawa niż zdrowy rozsądek. Jeśli streścimy to tak, jak dwie osoby rozmawiające, standard jest najlepszym sposobem, w jaki mogą dokładnie zrozumieć się nawzajem w minimalnych słowach w minimalnym czasie. W naszym przypadku "minimalne słowa" to optymalizacja przepustowości pod kątem wydajności transportu, a "dokładnie zrozumieć" to struktura wydajności parsera; która ostatecznie kończy się im mniej danych, a tym wspólna struktura; tak, że może przejść przez otwór na szpilkę i może być przetwarzane przez wspólny zakres (przynajmniej początkowo).

Prawie w każdym sugerowanym przypadku widzę osobne odpowiedzi dla scenariusza "sukces" i "błąd", co jest dla mnie niejednoznaczne. Jeśli w tych dwóch przypadkach odpowiedzi są różne, to dlaczego tak naprawdę musimy umieścić tam flagę "sukces"? Czy nie jest oczywiste, że brak "błędu" jest "sukcesem"? Czy możliwe jest uzyskanie odpowiedzi, w której "sukces" jest prawdziwy z ustawionym "błędem"? Czy sposób, "sukces" jest fałszywy bez "błąd" ustawiony? Tylko jeden flaga nie wystarczy? Wolałbym mieć tylko flagę "błąd" , ponieważ wierzę, że będzie mniej "błędu" niż "sukcesu".

Również, czy naprawdę powinniśmy uczynić "błąd" flagą? Co zrobić, jeśli chcę odpowiedzieć wieloma błędami walidacji? Uważam więc, że bardziej efektywne jest posiadanie węzła "Error" z każdym błędem jako potomkiem tego węzła; gdzie pusty (liczy się do zera) węzeł "Error" oznaczałby "sukces".

 0
Author: Broken Arrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-30 19:40:54

NAJLEPSZA odpowiedź dla web API, które mogą łatwo zrozumieć deweloperzy mobilni.

To jest odpowiedź "sukces"

{  
   "ReturnCode":"1",
   "ReturnMsg":"Successfull Transaction",
   "ReturnValue":"",
   "Data":{  
      "EmployeeName":"Admin",
      "EmployeeID":1
   }
}

Jest to odpowiedź "błąd"

{
    "ReturnCode": "4",
    "ReturnMsg": "Invalid Username and Password",
    "ReturnValue": "",
    "Data": {}
}
 -3
Author: Manish Vadher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-10 04:40:31