Open jmcanterafonseca opened 5 years ago
Actually, there was a similar discussion before. I think example 1 can be already done via JSON-LD references but this wouldn't be JSON Schema compatible. Your example already works if you copy the contents of input into a JSON Schema processor.
Example 2 is a more complicated case. A normal JSON Schema processor cannot understand this since the words properties
and then status
is not JSON Schema keywords, so a JSON Schema processor will not look inside them. The solution would be to create a JSON Schema instance for each place that contains a JSON Schema (input, output, subscription, etc.) and then always integrate the definitions into it. So one would need to generate as a preprocessing step of the TD:
"overheating": {
"definitions": {
"MyProperty": {
"type": "object",
"properties": {
"a": {
"type": "string"
}
}
},
"data":{ "$ref": "#/definitions/MyProperty" },
"forms": [{ "href": "https://mylamp.example.com/status" } ]
}
I think this would create a useful but complicated way of specifying payloads. Also I don't remember seeing something like this in Plugfests. Additionally, this would work for input, output, subscription, data, cancellation but not for properties (affordance) since the JSON Schema is not separated.
It could be useful to look at how ajv deals with something similar: https://github.com/epoberezkin/ajv-merge-patch
@egekorkan I strongly recommend against the $merge
keyword that ajv uses. After a discussion spanning six drafts, two sets of spec editors, two github repositories, upwards of 10 github issues, and well over 500 comments on those issues (over 200 on the final consolidated issue alone), we (the JSON Schema organization) decided to reject this proposal in favor of several others that, together, cover the various known use cases.
I can address this in more detail if/when the group revisits JSON Schema stuff.
Thank you @handrews , it was just a suggestion from reading online and I didn't have a strong opinion about it. The group will revisit the JSON Schema for somehow compacting the schemas that are used multiple times in a TD. I am not able to find the presentation but it was presented by @sebastiankb in the W3C TPAC 2019. The slot is this. @sebastiankb could you upload your presentation?
The group will revisit the JSON Schema for somehow compacting the schemas that are used multiple times in a TD.
It's been quite some time since I looked at the TD. Is there no place to store and $ref
re-usable schemas?
There is no defined place to store schemas to be re-used. As in example 2 above, one can define a definitions object but not every TD or JSON Schema processor will understand that.
Here is a suggested simple way to solve the issue:
"dataSchemas"
map into the root of a TD, which includes reusable schema
objects
of type TD "DataSchema"."schema"
key to refer to a reusable schema
by its name;reusable schema
and/or override its properties."schema"
references using a custom algorithm.Example TD:
{
...
"properties": {
"temperature": {
...
"schema": "temperatureValue",
"readOnly": true (EXTEND)
}
},
"actions": {
"setOverheatThreshold": {
...
"input": {
"schema": "temperatureValue",
"minimum": 20 (OVERRIDE)
}
}
},
...
"dataSchemas": {
"temperatureValue": {
"type": "number",
"minimum": -50,
"maximum": 50,
"unit": "Celsius"
}
}
}
Example TD after resolution:
{
...
"properties": {
"temperature": {
...
"type": "number",
"minimum": -50,
"maximum": 50,
"unit": "Celsius",
"readOnly": true (EXTED)
}
},
"actions": {
"setOverheatThreshold": {
...
"input": {
"type": "number",
"minimum": 20, (OVERRIDE)
"maximum": 50,
"unit": "Celsius"
}
}
},
...
}
Resolution algorithm:
function resolveReusableSchemas(td){
if(!td.dataSchemas){
return td;
}
if(td.properties){
for (let key in td.properties){
resolveDataSchema(td.properties[key]);
}
}
if(td.actions){
for (let key in td.actions){
resolveDataSchema(td.actions[key].input);
resolveDataSchema(td.actions[key].output);
}
}
if(td.events){
for (let key in td.events){
resolveDataSchema(td.events[key].data);
resolveDataSchema(td.events[key].subscription);
resolveDataSchema(td.events[key].cancellation);
}
}
delete td.dataSchemas; // optional
return td;
}
function resolveDataSchema(dataSchemaObj){
if(dataSchemaObj && dataSchemaObj.schema){
let reusableSchemaObj = td.dataSchemas[dataSchemaObj.schema];
if(reusableSchemaObj){
for (let key in reusableSchemaObj){
// do not overwrite existing properties
if(!(key in dataSchemaObj)){
dataSchemaObj[key] = reusableSchemaObj[key];
}
}
// delete the 'schema' property after resolution
delete dataSchemaObj.schema;
}
}
}
@TuranElchuev
use other properties to extend the reusable schema and/or override its properties.
Keep in mind that JSON Schema is a constraint system. It is not possible to override constraints. You can add more constraints (and/or attach more annotations- which is more flexible as the consuming application can decide which annotations are significant), but you cannot lift them.
Should be evaluated together with #307
TL;DR Enable "$ref" in the Data Schema Vocabulary Definitions of a TD. It will make things clearer and easier
JSON Schema content could be reused from existing API descriptions or defined in the TD itself.
What makes me wonder if TD could have just a
definitions
section the same as JSON Schema and insideinput
,output
,subscription
, etc. just reuse definitions from thedefinitions
section ... (instead of inlining schemas which make things a bit weird). it would save a lot of JSON Schema specification verbosity and will make the TD much more clearer, IMHO.See example 1 (external JSON Schema): (
$ref
would be resolved taking into account thebase``) See example 2 (from a
definitions` section inside the TD)Example 1:
Example 2: