JSON-WSP

From Wikipedia, the free encyclopedia

JSON-WSP (JavaScript Object Notation Web-Service Protocol) is a web-service protocol that uses JSON[1] for service description, requests and responses. It is very much inspired from JSON-RPC, but the lack of a service description specification with documentation in JSON-RPC sparked the design of JSON-WSP.

The description format has the same purpose for JSON-WSP as WSDL has for SOAP or IDL for CORBA, which is to describe the types and methods used in a given service. It also describes inter-type relations (i.e. nested types) and defines which types are expected as method arguments and which types the user can expect to receive as method return values. Finally the description opens the possibility to add documentation on service, method, parameter and return levels.

Communication between clients and a JSON-WSP server is carried out using HTTP[2] POST requests and responses, with the JSON objects as data with the content-type application/json.[3]

Specifications

JSON-WSP consists of four JSON object specifications:

Specification Description
description Service description specification (like WSDL). This specification describes methods, method parameters, types and return types. It also supports user documentation on service, method and parameter levels.
request Specification for JSON requests. It contains information about which method that is to be invoked and all the arguments for the method call. Arguments in the request must obey the parameter definition of the same method described in the corresponding JSON-WSP description.
response Specification for JSON responses. The response object contains the result of a service method invocation. The return type must obey the defined return type of the same method in the corresponding JSON-WSP description.
fault Specification for JSON fault responses. The fault object contains a fault code and a fault string. The fault information specifies whether the fault occurred on the client or server side. Depending on the server side service framework more detailed information can be extracted, i.e. the filename and line number where the fault occurred.

NOTE: JSON-WSP specification 1.0 is still not final. Please refer to the real world example in this article to get an idea of how the specification is going to be structured. The current state of the actual specification is kept at launchpad.net:.[4] An RFC proposal is currently being created and hopefully accepted within a couple of months.

Understanding the specification notation

Building blocks

  • If the name of the building-block being defined starts with rx-, it means that the definition is a regular expression. In these definitions square brackets have the role of defining character classes and parentheses have the role of defining capturing groups.
  • In all other cases, square brackets notate lists and parentheses notate either a decision::
    ( d1 | d2 | ... )
    a repetition of 0-many:
    ( ... )*
    a repetition 1-many:
    ( ... )+
    or something optional:
    ( ... )?

Common building-blocks

<rx-freetext> = ".*"
 
<rx-identifier> = "[a-zA-Z_][a-zA-Z0-9_]*"
 
<rx-number> = [0-9]+
 
<rx-boolean> = (true|false)
 
<key> = <rx-identifier>
 
<primitive-value> = ( <rx-freetext> | <rx-number> | <rx-boolean> )
 
<value> = (
    <primitive-value> |
    [ ( <value>, )* ] |
    { ( <key>: <value>, )* } )
 
<method-name> = <rx-identifier>
 
<service-name> = <rx-identifier>

Description object

Additional building-blocks

<primitive> = ( "string" | "number" | "float" | "attachment" )
 
<service-locator> = <rfc-1738 compliant string>
 
<type-name> = <rx-identifier>
 
<member-name> = <rx-identifier>
 
<multi-type> = ( <primitive> | <type-name> | [<primitive>] | [<type-name>] )
 
<doc-string> = <rx-freetext>
 
<param-name> = <rx-identifier>
 
<def-order> = <rx-number>
 
<param-optional> = <rx-boolean>

Specification

{
    "type": "jsonwsp/description",
    "version": "1.0",
    "servicename": <service-name>,
    "url": <service-locator>,
    "types": { (
        <type-name>: { ( 
            <member-name>: <multi-type> )+
        } )*
    },
    "methods": { ( 
        <method-name>: { 
            "doc_lines": [ ( <doc-string>, )* ],
            "params": { ( 
                <param-name>: { 
                    "doc_lines": [ ( <doc-string>, )* ],
                    "def_order": <def-order>,
                    "type": <multi-type>,
                    "optional": <param-optional>
                }, )* 
            },
            "ret_info": {
                "doc_lines": [ ( <doc-string>, )* ],
                "type": <multi-type>
            } 
        } )+
    }
}

Descriptions

<service-locator>: The service endpoint URL that accepts JSON-WSP POST request objects.

<service-name>: Service name is case sensitive. It identifies a specific service exposed on a specific server.

doc_lines: Each doc-string contained in a doc_lines list reflects a single line of documentation that relates to the parent object of the doc_lines..

Request object

The request object contains information about which method to invoke and what arguments to invoke the method with. It also stores information about the type and version of itself.

The optional mirror value can be used to send information from the client which will then be reflected by the server and returned unchanged in the response object's reflection value. This feature allows clients to send multiple requests to a method and send request identification values that can be intercepted by the client's response handler. This is often necessary from javascript if more than one request is being processed simultaneously by the server and the response order is unknown by the client.

Specification

{
    "type": "jsonwsp/request",
    "version": "1.0",
    "methodname": <method-name>,
    "args": { ( <key>: <value>, )* }(,
    "mirror": <value> )?
}

Response object

Specification

The reflection value is an unchanged server reflection of the request object's mirror value. It is marked as optional because it is the client that controls via the request whether it is there or not.

{
    "type": "jsonwsp/response",
    "version": "1.0",
    "servicename": <service-name>,
    "methodname": <method-name>,
    "result": <value>(,
    "reflection": <value> )?
}

Fault response object

Additional building-blocks

<fault-code> = ( "incompatible" | "client" | "server" )
 
<fault-string> = <rx-freetext>
 
<fault-filename> = <rx-freetext>
 
<fault-lineno> = <rx-number>

Specification

{
    "type": "jsonwsp/fault",
    "version": "1.0",
    "fault": {
        "code": <fault-code>,
        "string": <fault-string>,
        ("detail": [ ( <fault-string>, )* ] ,)?
        ("filename": <fault-filename>,)?
        ("lineno": <fault-lineno>,)?
    }(,
    "reflection": <value> )?
}

Descriptions

<fault-code>: The meanings of the possible fault-codes:

  • "incompatible": Client version of JSON-WSP is incompatible with the server version of JSON-WSP. Typically one will encounter this type of fault-code if there is a version major in difference between the client and the server.
  • "server": An error occurred on the server side after the client request has been successfully consumed.
  • "client": The clients request could not be consumed by the server due to incorrect format or missing required arguments etc.

Real world example

Description

{
    "type": "jsonwsp/description",
    "version": "1.0",
    "servicename": "UserService",
    "url": "http://testladon.org:80/proxy.php?path=UserService/jsonwsp",
    "types": {
        "Group": {
            "group_id": "number",
            "display_name": "string",
            "name": "string",
            "members": ["User"]
        },
        "User": {
            "username": "string",
            "user_id": "number",
            "mobile": "string",
            "age": "number",
            "given_name": "string",
            "surname": "string"
        },
        "CreateUserResponse": {
            "user_id": "number",
            "success": "boolean"
        }
    },
    "methods": {
        "listUsers": {
            "doc_lines": ["List Users that have a username, given_name or surname that matches a given filter."],
            "params": {
                "name_filter": {
                    "def_order": 1,
                    "doc_lines": ["String used for filtering the resulting list of users."],
                    "type": "string",
                    "optional": false
                }
            },
            "ret_info": {
                "doc_lines": ["List of users."],
                "type": ["User"]
            }
        },
        "listGroups": {
            "doc_lines": ["List Groups that have a name or display_name that matches a given filter."],
            "params": {
                "name_filter": {
                    "def_order": 1,
                    "doc_lines": ["String used for filtering the resulting list of groups."],
                    "type": "string",
                    "optional": false
                }
            },
            "ret_info": {
                "doc_lines": ["List of groups."],
                "type": ["Group"]
            }
        },
        "createUser": {
            "doc_lines": ["Create a new user account."],
            "params": {
                "username": {
                    "def_order": 1,
                    "doc_lines": ["Unique username for the new user account."],
                    "type": "string",
                    "optional": false
                },
                "given_name": {
                    "def_order": 2,
                    "doc_lines": ["First name."],
                    "type": "string",
                    "optional": false
                },
                "surname": {
                    "def_order": 3,
                    "doc_lines": ["Last name."],
                    "type": "string",
                    "optional": false
                },
                "mobile": {
                    "def_order": 4,
                    "doc_lines": ["Optional mobile number."],
                    "type": "string",
                    "optional": true
                },
                "age": {
                    "def_order": 5,
                    "doc_lines": ["Optional age of the person behind the account."],
                    "type": "number",
                    "optional": true
                }
            },
            "ret_info": {
                "doc_lines": [],
                "type": "CreateUserResponse"
            }
        }
    }
}

Service call 1

Request

{
    "type": "jsonwsp/request",
    "version": "1.0",
    "methodname": "createUser",
    "args": {
        "username": "bettyw",
        "given_name": "Betty",
        "surname": "Wilson",
        "mobile": "555-3423444"
    },
    "mirror": {
        "id": 2
    }
}

Response

{
    "type": "jsonwsp/response",
    "version": "1.0",
    "servicename": "UserService",
    "method": "createUser",
    "result": {
        "user_id": 324,
        "success": true
    }
    "reflection": {
        "id": 2
    }
}

Service call 2

Request

{
    "type": "jsonwsp/request",
    "version": "1.0",
    "methodname": "listUsers",
    "args": {
        "name_filter": "jack"
    }
}

Response

{
    "type": "jsonwsp/response",
    "version": "1.0",
    "servicename": "UserService",
    "method": "listUsers",
    "result": [{
        "username": "jackp",
        "user_id": 153,
        "mobile": "555-377843",
        "age": 34,
        "given_name": "Jack",
        "surname": "Petersen"
    }, {
        "username": "bradj",
        "user_id": 321,
        "mobile": "555-437546",
        "age": 27,
        "given_name": "Brad",
        "surname": "Jackson"
    }]
}

Attachments

The attachment type is new in JSON-WSP. It can be used anywhere in the description as a primitive type. In requests and responses that involve attachments, the message format must be multipart/related where the attachments are transported as mimeparts of media type: application/octet-stream with no Content-Transfer-Encoding (only raw binary). Mimeparts must have a unique CONTENT-ID in their entity headers. Attachment values in the JSON-WSP request/response objects must match the regular expression "^cid:(.+)$" where the capture group maps to one of the mimepart's CONTENT-ID.

Attachment service description example

The following example shows what a simple JSON-WSP description with attachments could look like:

{
    "type": "jsonwsp/description",
    "version": "1.0",
    "url": "http://mysite.com/TransferService/jsonwsp",
    "servicename": "TransferService",
    "types": {
        "File": {
            "data": "attachment",
            "name": "string"
        }
    }, 
    "methods": {
        "upload": {
            "ret_info": {
                "doc_lines": [],
                "type": "number"
            },
            "doc_lines": [],
            "params": {
                "incoming": {
                    "def_order": 1,
                    "doc_lines": [],
                    "type": [ "File" ],
                    "optional": false
                }
            }
        }
    }
}

Attachment service request example

A request to the method "upload" described above could look like this:

Content-Type: multipart/related; boundary="2676ff6efebdb664f8f7ccb34f864e25"
 
--2676ff6efebdb664f8f7ccb34f864e25
Content-Type: application/json, charset=UTF-8
Content-ID: body
 
{
    "type": "jsonwsp/request",
    "version": "1.0",
    "methodname": "upload",
    "args": {
        "incoming": [ {
            "data": "cid:img2354.png",
            "name": "face.png"
        }, {
            "data": "cid:cv.pdf",
            "name": "cv.pdf"
        } ]
    }
}
--2676ff6efebdb664f8f7ccb34f864e25
Content-Type: application/octet-stream
Content-ID: img2354.png
 
<png-image binary data>
--2676ff6efebdb664f8f7ccb34f864e25
Content-Type: application/octet-stream
Content-ID: cv.pdf
 
<pdf-image binary data>
--2676ff6efebdb664f8f7ccb34f864e25--

Server Implementations

  • ladon at PyPI Ladon is a python-based framework that exposes json-wsp and other protocols
  • ladon at ladonize.org ladonize.org is the official homepage for ladon. It contains running demos.
  • pfacka/jsonwsp A Python JSON-WSP server implentation]

Client Implementations

See also

  • JSON-RPC JSON-based remote procedure call

References

External links

This article is issued from Wikipedia. The text is available under the Creative Commons Attribution/Share Alike; additional terms may apply for the media files.