Resumen
JSON-RPC es un protocolo de llamada a procedimientos remotos (RPC) ligero y sin estado. Esta especificación define principalmente varias estructuras de datos y las reglas relativas a su procesamiento. Es independiente del medio de transporte, en el sentido de que los conceptos pueden utilizarse dentro del mismo proceso, a través de sockets, por HTTP o en diversos entornos de paso de mensajes. Utiliza JSON (RFC 4627) como formato de datos.
¡Está diseñado para ser sencillo!
Convenciones
Los términos clave «DEBE», «NO DEBE», «OBLIGATORIO», «DEBERÁ», «NO DEBERÁ», «DEBERÍA», «NO DEBERÍA», «RECOMENDADO», «PUEDE» y «OPCIONAL» que aparecen en este documento deben interpretarse tal y como se describe en el RFC 2119.
Dado que JSON-RPC utiliza JSON, cuenta con el mismo sistema de tipos (véase http://www.json.org o RFC 4627). JSON puede representar cuatro tipos primitivos (cadenas, números, valores booleanos y nulos) y dos tipos estructurados (objetos y matrices). El término «primitivo» en esta especificación hace referencia a cualquiera de esos cuatro tipos primitivos de JSON. El término «estructurado» hace referencia a cualquiera de los tipos estructurados de JSON. Siempre que este documento se refiera a cualquier tipo de JSON, la primera letra se escribirá en mayúscula: objeto, matriz, cadena, número, booleano, nulo. «True» y «False» también se escriben con mayúscula.
Todos los nombres de miembros intercambiados entre el cliente y el servidor que se tengan en cuenta para cualquier tipo de coincidencia deben considerarse sensibles a mayúsculas y minúsculas. Se puede dar por hecho que los términos «función», «método» y «procedimiento» son intercambiables.
El cliente se define como el origen de los objetos «Request» y el gestor de los objetos «Response».
El servidor se define como el origen de los objetos «Response» y el gestor de los objetos «Request».
Una implementación de esta especificación podría desempeñar fácilmente ambas funciones, incluso al mismo tiempo, para distintos clientes o para el mismo cliente. Esta especificación no aborda ese nivel de complejidad.
Compatibilidad
Es posible que los objetos de solicitud y respuesta de JSON-RPC 2.0 no funcionen con los clientes o servidores JSON-RPC 1.0 existentes. Sin embargo, es fácil distinguir entre ambas versiones, ya que la 2.0 siempre tiene un miembro denominado «jsonrpc» con un valor de cadena «2.0», mientras que la 1.0 no lo tiene. La mayoría de las implementaciones de la versión 2.0 deberían intentar gestionar los objetos de la versión 1.0, aunque no se tengan en cuenta los aspectos de comunicación entre pares y de sugerencias de clases propios de la versión 1.0.
Objeto de solicitud
Una llamada RPC consiste en enviar un objeto `Request` a un servidor. El objeto `Request` tiene los siguientes miembros:
jsonrpc – Una cadena que especifica la versión del protocolo JSON-RPC. DEBE ser exactamente «2.0».
método: una cadena que contiene el nombre del método que se va a invocar. Los nombres de métodos que comienzan con la palabra «rpc» seguida de un punto (U+002E o ASCII 46) están reservados para métodos y extensiones internos de RPC y NO DEBEN utilizarse para ningún otro fin.
params: un valor estructurado que contiene los valores de los parámetros que se utilizarán durante la invocación del método. Este miembro PUEDE omitirse.
id: un identificador establecido por el cliente que DEBE contener una cadena, un número o el valor NULL si se incluye. Si no se incluye, se considera que se trata de una notificación. Normalmente, el valor NO DEBERÍA ser nulo [1] y los números NO DEBERÍAN contener decimales [2]
El servidor DEBE responder con el mismo valor en el objeto «Response» si se incluye. Este miembro se utiliza para establecer una correlación entre el contexto de ambos objetos.
[1] No se recomienda utilizar «Null» como valor para el miembro «id» en un objeto «Request», ya que esta especificación utiliza el valor «Null» para las respuestas cuyo «id» se desconoce. Además, dado que JSON-RPC 1.0 utiliza el valor «Null» para el «id» de las notificaciones, esto podría generar confusión a la hora de gestionarlas.
[2] Las fracciones pueden plantear problemas, ya que muchas fracciones decimales no pueden representarse exactamente como fracciones binarias.
Notificación
Una «Notificación» es un objeto «Request» que carece del miembro «id». Un objeto «Request» que sea una «Notificación» indica que el cliente no está interesado en el objeto «Response» correspondiente y, por lo tanto, no es necesario devolver ningún objeto «Response» al cliente. El servidor NO DEBE responder a una «Notificación», incluidas aquellas que formen parte de una solicitud por lotes.
Las notificaciones, por definición, no se pueden confirmar, ya que no cuentan con un objeto «Response» que se pueda devolver. Por lo tanto, el cliente no tendría conocimiento de ningún error (como, por ejemplo, «Parámetros no válidos» o «Error interno»).
Estructuras de parámetros
Si existen, los parámetros de la llamada RPC DEBEN proporcionarse como un valor estructurado, ya sea por posición a través de una matriz o por nombre a través de un objeto.
- por posición: los parámetros DEBEN ser una matriz que contenga los valores en el orden previsto por el servidor.
- por nombre: los parámetros DEBEN ser un objeto, con nombres de miembros que coincidan con los nombres de los parámetros esperados por el servidor. La ausencia de los nombres esperados PUEDE provocar que se genere un error. Los nombres DEBEN coincidir exactamente, incluyendo las mayúsculas y minúsculas, con los parámetros esperados por el método.
Objeto de respuesta
Cuando se realiza una llamada RPC, el servidor DEBE responder con una respuesta, salvo en el caso de las notificaciones. La respuesta se expresa como un único objeto JSON, con los siguientes miembros:
jsonrpc – Una cadena que especifica la versión del protocolo JSON-RPC. DEBE ser exactamente «2.0».
resultado: este miembro es OBLIGATORIO si la operación se ha realizado correctamente.
Este miembro NO DEBE existir si se ha producido un error al invocar el método.
El valor de este miembro viene determinado por el método invocado en el servidor.
error – Este miembro es OBLIGATORIO en caso de error.
Este miembro NO DEBE existir si no se ha producido ningún error durante la invocación.
El valor de este miembro DEBE ser un objeto tal y como se define en la sección 5.1.
id – Este miembro es OBLIGATORIO.
DEBE coincidir con el valor del miembro «id» del objeto de solicitud.
Si se ha producido un error al detectar el «id» en el objeto de solicitud (por ejemplo, error de análisis o solicitud no válida), DEBE ser nulo.
DEBE incluirse o bien el miembro «result» o bien el miembro «error», pero NO DEBEN incluirse ambos miembros.
Objeto de error
Cuando se produce un error en una llamada RPC, el objeto de respuesta DEBE contener el miembro «error», cuyo valor debe ser un objeto que incluya los siguientes miembros:
código: un número que indica el tipo de error que se ha producido.
DEBE ser un número entero.
mensaje: una cadena de caracteres que ofrece una breve descripción del error.
El mensaje DEBERÍA limitarse a una sola frase concisa.
data: un valor primitivo o estructurado que contiene información adicional sobre el error.
Se puede omitir.
El valor de este miembro lo define el servidor (por ejemplo, información detallada sobre el error, errores anidados, etc.).
Los códigos de error comprendidos entre -32768 y -32000, ambos inclusive, están reservados para errores predefinidos. Cualquier código dentro de este rango que no se defina explícitamente a continuación queda reservado para su uso futuro. Los códigos de error son prácticamente los mismos que los sugeridos para XML-RPC en la siguiente URL: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
| código | mensaje | significado |
|---|---|---|
| -32700 | Error de análisis | El servidor ha recibido un JSON no válido. Se ha producido un error en el servidor al analizar el texto JSON. |
| -32600 | Solicitud no válida | El JSON enviado no es un objeto Request válido. |
| -32601 | Método no encontrado | El método no existe / no está disponible. |
| -32602 | Parámetros no válidos | Parámetros de método no válidos. |
| -32603 | Error interno | Error interno de JSON-RPC. |
| de -32099 a -32000 | Error del servidor | Reservado para errores de servidor definidos por la implementación. |
El espacio restante está disponible para errores definidos por la aplicación.
Lote
Para enviar varios objetos «Request» al mismo tiempo, el cliente PUEDE enviar una matriz que contenga dichos objetos.
El servidor debe responder con un array que contenga los objetos Response correspondientes, una vez que se hayan procesado todos los objetos Request del lote. DEBE existir un objeto Response por cada objeto Request, salvo que NO DEBE haber ningún objeto Response para las notificaciones. El servidor PUEDE procesar una llamada RPC por lotes como un conjunto de tareas concurrentes, procesándolas en cualquier orden y con cualquier grado de paralelismo.
Los objetos «Response» devueltos por una llamada por lotes PUEDEN aparecer en cualquier orden dentro de la matriz. El cliente DEBERÍA establecer la correspondencia entre los contextos del conjunto de objetos «Request» y el conjunto resultante de objetos «Response» basándose en el miembro «id» de cada objeto.
Si la propia llamada RPC por lotes no se reconoce como un JSON válido o como un array con al menos un valor, la respuesta del servidor DEBE ser un único objeto «Response». Si no hay ningún objeto «Response» en el array «Response» tal y como se va a enviar al cliente, el servidor NO DEBE devolver un array vacío, sino que no debe devolver nada en absoluto.
Ejemplos
Sintaxis:
--> data sent to Server <-- data sent to Client
Llamada RPC con parámetros posicionales:
--> {"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}Llamada RPC con parámetros con nombre:
--> {"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}Una notificación:
--> {"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]}
--> {"jsonrpc": "2.0", "method": "foobar"}Llamada RPC a un método inexistente:
--> {"jsonrpc": "2.0", "method": "foobar", "id": "1"}
<-- {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Procedure not found."}, "id": "1"}Llamada RPC con JSON no válido:
--> {"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz]
<-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error."}, "id": null}Llamada RPC con un objeto Request no válido:
--> {"jsonrpc": "2.0", "method": 1, "params": "bar"}
<-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null}Llamada RPC «Batch», JSON no válido:
--> [ {"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},{"jsonrpc": "2.0", "method" ]
<-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error."}, "id": null}Llamada RPC con un array vacío:
--> []
<-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null}Llamada RPC con un lote no válido (pero no vacío):
--> [1]
<-- [ {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null} ]Llamada RPC con un lote no válido:
--> [1,2,3]
<-- [
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null},
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null},
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null}
]Llamada RPC por lotes:
--> [
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"},
{"foo": "boo"},
{"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"},
{"jsonrpc": "2.0", "method": "get_data", "id": "9"}
]
<-- [
{"jsonrpc": "2.0", "result": 7, "id": "1"},
{"jsonrpc": "2.0", "result": 19, "id": "2"},
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null},
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found."}, "id": "5"},
{"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"}
]Llamada RPC «Batch» (todas las notificaciones):
--> [
{"jsonrpc": "2.0", "method": "notify_sum", "params": [1,2,4]},
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
]
<-- //Nothing is returned for all notification batchesExtensiones
Los nombres de métodos que comienzan por «rpc.» están reservados para las extensiones del sistema y NO DEBEN utilizarse para ningún otro fin. Cada extensión del sistema se define en una especificación correspondiente. Todas las extensiones del sistema son OPCIONALES.
Derechos de autor (C) 2007-2010 del Grupo de Trabajo JSON-RPC
Este documento y sus traducciones pueden utilizarse para implementar JSON-RPC; pueden copiarse y facilitarse a terceros; y pueden elaborarse, copiarse, publicarse y distribuirse, total o parcialmente, obras derivadas que lo comenten, lo expliquen o faciliten su implementación, sin restricción alguna, siempre que se incluyan el aviso de derechos de autor anterior y este párrafo en todas esas copias y obras derivadas. Sin embargo, el presente documento no puede modificarse de ninguna manera.
Los permisos limitados concedidos anteriormente son perpetuos y no serán revocados.
El presente documento y la información que contiene se facilitan «TAL CUAL» y SE EXCLUYEN TODAS LAS GARANTÍAS, EXPRESAS O IMPLÍCITAS, INCLUIDAS, ENTRE OTRAS, CUALQUIER GARANTÍA DE QUE EL USO DE LA INFORMACIÓN AQUÍ CONTENIDA NO INFRINGIRÁ NINGÚN DERECHO, ASÍ COMO CUALQUIER GARANTÍA IMPLÍCITA DE COMERCIABILIDAD O DE ADECUACIÓN PARA UN FIN DETERMINADO.