JSON-RPC – protokół zdalnego wywoływania procedur implementowany zazwyczaj ponad HTTP, który jako dane transportowe wykorzystuje obiekty JSON-a. Jest to bardzo prosty protokół (bardzo podobny do XML-RPC), definiujący tylko najbardziej użyteczne typy danych i komendy. JSON-RPC pozwala na powiadomienia (informacje przesyłane do serwera, nie wymagające odpowiedzi) oraz możliwość wysyłania do serwera wielu wywołań, mogących uzyskać odpowiedź poza kolejnością wysyłki.

Historia edytuj

Pierwsza wersja protokołu została przedstawiona w 2005 roku, najnowszą wersję 2.0 ogłoszono w 2010 roku:

Wersja Opis Data
1.0 wersja oryginalna[1] – obecnie uznawana jako oficjalna 2005
1.1 WD wersja robocza[2] – dodaje nazwy parametrów, dodaje konkretne kody błędów i dodaje funkcje introspekcji 2006-08-07
1.1 Alt sugestia prostego JSON-RPC 1.1[3] – alternatywna propozycja dla wersji 1.1 WD 2007-05-06
1.2 propozycja[4] – późniejsza korekta tego dokumentu to wersja 2.0 specyfikacji 2007-12-27
2.0 propozycja specyfikacji[5] 2009-05-24
2.0 (Revised) propozycja specyfikacji[6] 2010-03-26

Użycie edytuj

JSON-RPC działa, wysyłając żądanie do serwera, implementując niniejszy protokół. Klient w takim przypadku jest typowo oprogramowaniem, które chce wywołać pojedynczą metodę zdalnego systemu. Wiele parametrów wejściowych może być przekazanych do zdalnej metody w postaci tablicy lub obiektu, natomiast sama metoda może również zwracać wiele danych wyjściowych (To zależy od realizowanych wersji). Zdalna metoda jest wywoływana przez wysłanie zapytania do zdalnej usługi za pomocą HTTP.

Kiedy używamy HTTP, to content-type może być definiowany jako application/json[7].

Wszystkie typy transferu są pojedynczymi obiektami, serializowane przy użyciu JSON[1]. Zapytanie jest wywołaniem określonej metody dostarczonej przez zdalny system. Musi zawierać trzy określone właściwości:

  • method – String z nazwą metody do wywołania.
  • params – Tablica obiektów, które będą przekazywane jako parametry do zdefiniowanej metody.
  • id – Wartość dowolnego typu, która jest używana do dopasowania reakcji do zapytania, na które udzielana jest odpowiedź.

Odbiorca musi udzielić prawidłowej odpowiedzi na wszystkie otrzymane zapytania. Odpowiedź musi zawierać właściwości wymienione poniżej:

  • result – Dane zwrócone przez wywoływane metody. Jeśli wystąpił błąd podczas wywoływania metody, wartość ta musi wynosić null.
  • error – Określony kod błędu (jeśli wystąpił błąd podczas wywoływania metody), w przeciwnym razie null.
  • id – Id zapytania, na które odpowiada.

Ponieważ istnieją sytuacje, w których odpowiedź nie jest potrzebna, a wręcz jest niepożądana, zostały wprowadzone zawiadomienia. Zawiadomienie jest podobne do zapytania. Różnica polega na braku id, które nie jest potrzebne, ponieważ nie oczekujemy odpowiedzi. W tym przypadku własności id powinny być pominięte (wersja 2.0) lub ustawione na null (wersja 1.0).

Przykłady edytuj

Zapytanie Klienta edytuj

 {"id": 1, "jsonrpc":"2.0", "method": "echo", "params": ["hello"]}

Odpowiedź Serwera edytuj

{"id": 1, "jsonrpc":"2.0", "error": null, "result": "hello"}

Istnieje także możliwość wywoływania wielu wywołań funkcji, wtedy poszczególne zapytanie przekazywane są w tablicy, a serwer zwraca tablicę odpowiedzi.

W poniższych przykładach --> oznacza dane wysyłane do serwisu (zapytanie), podczas gdy <-- oznacza dane pochodzące z serwisu (chociaż tym kierunku często nazywa się to odpowiedzią, w architekturze klient-serwer w zależności od wersji JSON-RPC nie musi to jednak oznaczać odpowiedzi na zapytanie).

Wersja 1.0 edytuj

Proste zapytanie i odpowiedź:

--> { "method": "echo", "params": ["Hello JSON-RPC"], "id": 1}
<-- { "result": "Hello JSON-RPC", "error": null, "id": 1}

W tym przykładzie przedstawiono części komunikatu na przykładzie zastosowania czatu. Usługa czatu wysyła powiadomienia dla każdej wiadomości, którą klient powinien otrzymać. Klient wysyła zapytania do czatu i oczekuje, pozytywnej odpowiedzi, że wiadomość została zapisana[1].

...
--> {"method": "postMessage", "params": ["Hello all!"], "id": 99}
<-- {"result": 1, "error": null, "id": 99}
<-- {"method": "handleMessage", "params": ["user1", "we were just talking"], "id": null}
<-- {"method": "handleMessage", "params": ["user3", "sorry, gotta go now, ttyl"], "id": null}
--> {"method": "postMessage", "params": ["I have a question:"], "id": 101}
<-- {"method": "userLeft", "params": ["user3"], "id": null}
<-- {"result": 1, "error": null, "id": 101}
...

Ponieważ pole params jest tablicą obiektów, następujący format również jest poprawny:

{
 "method": "methodnamehere",
 "params": [
            {
             "firstparam": "this contains information of the firstparam.",
             "secondparam": 1121211234,
             "thirdparam": "this contains information of the thirdparam."
            },
            {
             "fourthparam": "this is already a different object.",
             "secondparam": "there can be same name fields in different objects.",
             "thirdparam": "this contains information of the thirdparam."
            }
           ],
 "id": 1234
}

Wersja 1.1 (Working Draft) edytuj

Format zawartości zapytania może być przedstawiona jak przykład poniżej:

{
"version": "1.1",
"method": "confirmFruitPurchase",
"id": "194521489",
"params": [
    [ "apple", "orange", "pear" ], 
    1.123 
]
}

Format odpowiedzi może wyglądać tak:

{
"version": "1.1",
"result": "done",
"error": null,
"id": "194521489"
}

Wersja 2.0 (Propozycja Specyfikacji) edytuj

Procedura Call z parametrami pozycyjnymi:

--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}
--> {"jsonrpc": "2.0", "method": "subtract", "params": [23, 42], "id": 2}
<-- {"jsonrpc": "2.0", "result": -19, "id": 2}

Procedura Call z nazwami parametrów:

--> {"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}
<-- {"jsonrpc": "2.0", "result": 19, "id": 3}
--> {"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}
<-- {"jsonrpc": "2.0", "result": 19, "id": 4}

Notyfikacja:

--> {"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]}
--> {"jsonrpc": "2.0", "method": "foobar"}

Procedura Call procedury nieistniejącej:

--> {"jsonrpc": "2.0", "method": "foobar", "id": 10}
<-- {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Procedure not found."}, "id": 10}

Procedura Call z nieprawidłowym JSON:

--> {"jsonrpc": "2.0", "method": "foobar", "params": "bar", "baz"]
<-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": null}

Procedura Call z nieprawidłowym JSON-RPC:

--> [1,2,3]
<-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid JSON-RPC."}, "id": null}
--> {"jsonrpc": "2.0", "method": 1, "params": "bar"}
<-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid JSON-RPC."}, "id": null}

Zobacz też edytuj

Przypisy edytuj

  1. a b c JSON-RPC 1.0 Specification (2005). [dostęp 2011-10-06]. [zarchiwizowane z tego adresu (2008-05-17)]. (ang.).
  2. JSON-RPC 1.1 Wd. JSON-RPC, 2006-08-07. [dostęp 2019-04-27]. (ang.).
  3. JSON-RPC 1.1 Alt. JSON-RPC, 2007-05-06. [dostęp 2019-04-27]. (ang.).
  4. JSON-RPC 1.2 proposal. JSON-RPC, 2007-12-27. [dostęp 2019-04-27]. (ang.).
  5. JSON-RPC 2.0 Specification proposal. JSON-RPC, 2009-05-24. [dostęp 2019-04-27]. (ang.).
  6. JSON-RPC 2.0. JSON-RPC, 2010-03-26. [dostęp 2019-04-27]. (ang.).
  7. RFC 4627. [dostęp 2011-10-06]. [zarchiwizowane z tego adresu (2011-07-17)].

Linki zewnętrzne edytuj