By including method definitions, JSON Schema can easily be extended to be a service descriptor for the RPC (remote procedure call) service JSON-RPC. JSON Schema provides robust type definition which can be utilized for defining types in method call contracts. In addition, using JSON Schema allows methods to be defined in the same manner as property definitions, so direct object/REST and RPC services can be defined in a uniform manner, and services can even support both direct object and RPC services.
A JSON Schema service descriptor is simply a JSON Schema with the additional definition for methods. For this specification, a schema will be used to denote a JSON Schema definition. A JSON Schema service descriptor is an JSON object with properties that correspond to available methods or procedures that can be called, and the values of the properties in the schema should contain a method definitions that provide the definition for how the methods should be called. A method definition can define various attributes of the method that define it's usage and valid values. A method definition follows the same format as a JSON Schema property definition except, that the type value must be "method", the property attributes describe the return value, and there are additional attributes "returns" which describes the type of the return value, and "params" which is an array of property definitions (or possibly an object if 1.1 supports objects as params). Here are the properties that are in addition to the standard JSON Schema property definition:
Property | Meaning |
type | Must be "method" for a method definition. |
returns | Must be a type definition. If it is not included, the return value is not needed, the method should be considered a notification. |
params | Must be an array of property definitions. Each property definition should also have a name property to define the name of parameters. A property definition with the name "*" can be used to define the type for additional parameters (in the case of variable parameters). Note: If objects as params is accepted as a valid value for JSON-RPC, this can be an object/schema as well, with property definitions for each property in the object. |
required | Specifically indicates whether the method MUST return a value. This is false by default. |
nullable | This indicates whether the return value may be a null. This is false by default. |
minimum | This indicates the minimum value for the return value when the type of the value is a number, or it indicates the minimum number of values in an array when an array is the return value. |
maximum | This indicates the maximum value for the return value when the type of the value is a number, or it indicates the maximum number of values in an array when an array is the return value. |
pattern | When the return value is a string, this provides a regular expression that the return string value must match. Regular expressions should follow the regular expression specification from ECMA 262/Perl 5. |
length | When the return value is a string, this indicates maximum length of the string. |
options | This provides an enumeration of possible values that are valid for the return value. |
unconstrained | When used in conjunction with the options property, this indicates a return value can be used that is not in the list of options. This has no meaning when the options property is not a sibling. |
description | This provides a description of the purpose the method. The value should be a string. "description":{"My method"} |
format | This indicates what format the data is among some predefined formats which may include:
|
In addition a service descriptor should contain the id and description properties, and may contain the version property as defined here:
Property | Meaning |
id | A unique identifier for the service. When possible, the id should represent the URL from the which service descriptor can be accessed (relative URLs are acceptable). |
description | This a description of the service. |
version | This is the version of the service. |
A service descriptor could look like (each top level property defines an available method/procedure):
{"divide": { "description":"Divide one number by another", "type":"method", "returns":"number", "params":[{"type":"number","name":"dividend","required":true}, {"type":"number","name":"divisor","required":true}] }, "sqrt": { "description":"Find the square root of a number", "type":"method", "returns":"number", "params":[{"type":"number","name":"square","required":true, "minimum":0,"description":"Number to find the square root of"}] }, "sqrtComplex": { "description":"Find the square root of a number including negative numbers", "type":"method", "returns":["number", {"realPart":{"type":"number"}, "imaginaryPart":{"type":"number"}}], "params":[{"type":"number","name":"square","required":true, "description":"Number to find the square root of"}] },Here you can see that we are utilizing various JSON Schema definitions such as union types (allowing for a "number" or a complex number object to be returned), and object definitions (complex number definition) in the type definitions.
"sum": {
"description":"Find the sum of the parameters",
"type":"method",
"returns":"number",
}
"params":[{"type":"number","name":"*",
"description":"Number to include in the sum"}]
},
"id":"http://math.com/mathMethods.schema"
,"description":"Some math methods. Strings as property/method definitions are ignored by JSON Schema validators, but this property can be used for a description."
{"firstName":{"type":"string"}, "lastName":{"type":"string"}, "friends":{"type":{"items":{"firstName":{"type":"string"}, "lastName":{"type":"string"}}}, "addFriend: {"type":"method", "description":"Adds a friend to this person"}, "params":[{"firstName":{"type":"string"}, "lastName":{"type":"string"}] },In this example, the schema defines methods that can be called (using JSON-RPC) on this object (http://www.myfriends.com/john) as well as properties that should be expected from this object/url. That is the object properties might look something like this (on HTTP what would be returned by GET, but no protocol needs to be assumed):
"id":"http://friends.com/friend.schema" }
{"firstName":"John","lastName":"Doe","friends":[]}Note that this example could be more DRY by using a JSON Referencing scheme to define a person definition, and reusing that definition for the friends array and the parameter definition, but this is not necessary.