Can we add support for JSON-Schema

432 views
Skip to first unread message

Martin Barker

unread,
Jul 17, 2018, 4:43:19 PM7/17/18
to JSON-RPC
I know JSON-Schema http://jsonschema.org is still in a draft state but I think it would be could if they could be provided them would be of benefit to everyone I think.

These are what I have mocked up they might need to be updated slightly.

Request
{
 
"$schema": "http://json-schema.org/schema#",
 
"type": "object",
 
"$id":"https://www.jsonrpc.org/schema/request",
 
"properties": {
 
"jsonrpc": {
           
"type":"string",
           
"format": "/2\\.0$"
       
},
 
"method":{
           
"type":"string",
           
"format":"^(?!rpc)([a-zA-Z]).*$"
       
},
       
"params":{
           
"type":"array"
       
},
       
"id":{
           
"type":["number", "string", "null"],
           
"format":"^\\d+|([a-zA-Z].*)$"
       
}
 
},
 
"required": ["jsonrpc", "method", "id"],
 
"additionalProperties": false
}

Notification
{
 
"$schema": "http://json-schema.org/schema#",
 
"type": "object",
 
"$id":"https://www.jsonrpc.org/schema/notification",
 
"properties": {
 
"jsonrpc": {
           
"type":"string",
           
"format": "/2\\.0$"
       
},
 
"method":{
           
"type":"string",
           
"format":"^(?!rpc)([a-zA-Z]).*$"
       
},
       
"params":{
           
"type":"array"
       
}
 
},
 
"required": ["jsonrpc", "method"],
 
"additionalProperties": false
}

Result
{
 
"$schema": "http://json-schema.org/schema#",
 
"type": "object",
 
"$id":"https://www.jsonrpc.org/schema/result",
 
"properties": {
 
"jsonrpc": {
           
"type":"string",
           
"format": "/2\\.0$"
       
},
       
"result":{
       
},
       
"id":{
           
"type":["number", "string", "null"],
           
"format":"^\\d+|([a-zA-Z].*)$"
       
}
 
},
 
"required": ["jsonrpc", "result"],
 
"additionalProperties": false
}

Error
{
 
"$schema": "http://json-schema.org/schema#",
 
"type": "object",
 
"$id":"https://www.jsonrpc.org/schema/error",
 
"properties": {
 
"jsonrpc": {
           
"type":"string",
           
"format": "/2\\.0$"
       
},
 
"error":{
           
"type":"object",
           
"properties":{
               
"code":{
                 
"type":"number"
               
},
               
"message":{
                 
"type":"string"
               
},
               
"data":{
               
}
           
},
             
"required":["code", "message"]
       
},
       
"id":{
           
"type":["number", "string", "null"],
           
"format":"^\\d+|([a-zA-Z].*)$"
       
}
 
},
 
"required": ["jsonrpc", "error"],
 
"additionalProperties": false
}

Aleksandras Novikovas

unread,
Jan 2, 2020, 3:57:05 PM1/2/20
to JSON-RPC
Here is another version of schemas:

Differences:
  • combined request and notification into one schema
  • combined result and error into one schema
  • request method can start with "rpc." - for example calling "rpc.discover" as proposed in OpenRPC
  • params in request can be either array or object
  • if id is string - it can be any string - specs does not define neither format nor characters used
  • error.code type chanded to integer
  • removed "additionalProperties": false - specs does not explicitly prohibit use of other properties in request/response/error objects
Note on batch requests - request schema validates single request on purpose:
if batch request is used - every single array element should be validated separately.

Request:
{
   "type": "object",
   "properties": {
       "jsonrpc": {
           "type": "string",
           "enum": [
               "2.0"
           ]
       },
       "id": {
           "type": [
               "string",
               "number",
               "null"
           ],
           "minLength": 1
       },
       "method": {
           "type": "string",
           "minLength": 1
       },
       "params": {
           "type": [
               "object",
               "array"
           ]
       }
   },
   "required": [
       "jsonrpc",
       "method"
   ]
}
Enter code here...

Response:
{
   "type": "object",
   "properties": {
       "jsonrpc": {
           "type": "string",
           "enum": [
               "2.0"
           ]
       },
       "id": {
           "type": [
               "string",
               "number",
               "null"
           ],
           "minLength": 1
       }
   },
   "oneOf": [
       {
           "properties": {
               "result": {}
           },
           "required": [
               "jsonrpc",
               "id",
               "result"
           ]
       },
       {
           "properties": {
               "error": {
                   "type": "object",
                   "properties": {
                       "code": {
                           "type": "integer"
                       },
                       "message": {
                           "type": "string",
                           "minLength": 1
                       },
                       "data": {}
                   },
                   "required": [
                       "code",
                       "message"
                   ]
               }
           },
           "required": [
               "jsonrpc",
               "id",
               "error"
           ]
       }
   ]
}



Martin Barker

unread,
Apr 26, 2021, 9:04:51 AM4/26/21
to JSON-RPC
So,
I agree with most of your changes however couple of comments.

  1. To your "if id is string - it can be any string - specs does not define neither format nor characters used" JSONRPC 2.0 spec clearly states, "Numbers SHOULD NOT contain fractional parts" and while I know it does not say "MUST NOT", I'm not sure if a Schema of a 2.0 Spec should allow practices against the recommendation of the specification if someone actually needs that then they could modify and create a local or app-specific copy. But up for debate by the group that's why I started this chain up was so others could be involved in the discussion.
  2. Another one for debate is should 2.0 Notification be using a merged with request schema to me it seems like the fact Null is allowed as an ID is for cross-compatibility with old spec systems so they would not be using a schema parser/ validator in that codebase. I think perhaps they should be separate to lower the processing of validation of payload data for a notification to keep processing as minimal as possible for notifications (thinking IOT devices)?

Aleksandras Novikovas

unread,
Apr 26, 2021, 12:14:28 PM4/26/21
to JSON-RPC
I did follow specs precisely.

To your points:
1. I would suggest to have two variants: exact and strict. For strict variant definition of "id" would be:
        "id": {
            "type": [
                "string",
                "number"
            ],
            "minLength": 1,
            "multipleOf": 1
        }
(null removed, "minLength": string with minimum length 1, "multipleOf": number only integer)
BTW: in your proposed schema "format" with regex applies only to strings, so numbers with fractions would be valid

2. In 2.0 only difference between request and notification is existence of  "id" field. I do not see any processing gains in single additional field validation.
Otherwise one would have to somehow decide which schema to use: request or notification. So I would oppose splitting notification and request schemas.

Martin Barker

unread,
Apr 27, 2021, 7:49:45 AM4/27/21
to JSON-RPC
Hello again,

1) I would agree with the 2 versions strict and exact might be the better way to go. I would say for the strict, why would you not just use the draft 7 "integer" type as you have with the error code? instead of "number" with a min length and multiple of, unless you're explicitly trying to negate the implementation disagreements in which case it should be the same for error code? just I do not say which way should be done but just that the same method is used in both cases.

2) "processing gains in single additional field validation," i think you need to this about lower power IoT Devices say an Arduino Nano, " Otherwise one would have to somehow decide which schema to use: request or notification" yeah that's my point if they are sending notifications they should be using the notification schema to make sure it's actually a notification. To me the whole point of schemas is to validate the data being used is correct for the purpose the data was created to merge them into one undermines the points of a schema IMO. but again this could be fixed by having a merged and separate so people pick for their specific use-case.

Explanation of where my opinion comes from in an example: In a TCP setup I want to send a notification but I have included an ID, so because it's a notification the sender is not going to wait to read the response so close the socket. so the receiver is going to build a response try to send it and then have to handle that the socket is closed and destroy that response it just built, in that scenario you're just wasting receiver resources and processing power. even in UDP you're still building and sending a response that's going to be ignored and a waste of resources on the receiver.
Whereas going this is a notification use the notification schema in the sender the schema failing with "you're sending an unsupported property" would fix that, it would also prevent it from having to be fixed in the future because having merged means it passed the test and seemingly works gets deployed to thousands of devices and then IT Dept noticed the server/s are having high resource utilization for the fix to be made of removing the "id" property than trying to deploy that update to all the devices. and yeah on PC it's easy to do the moment you go IoT devices that becomes 1000 times more difficult to deploy. there is also loading a smaller schema is a lower memory footprint for the string of the schema on the sender device.

Anyway, I would like to know what others in the group think about even having a schema and if we should what their input to the conversation of how each thinks it should be built.
Reply all
Reply to author
Forward
0 new messages