Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gbroques/json-schema-interproperty-expressions
JSON Schema extension for arithmetic and relational constraints between properties.
https://github.com/gbroques/json-schema-interproperty-expressions
inter-property-constraints json-schema json-schema-form json-schema-forms validation-rules
Last synced: 22 days ago
JSON representation
JSON Schema extension for arithmetic and relational constraints between properties.
- Host: GitHub
- URL: https://github.com/gbroques/json-schema-interproperty-expressions
- Owner: gbroques
- Created: 2023-05-25T20:08:09.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2023-05-26T18:07:53.000Z (over 1 year ago)
- Last Synced: 2024-11-13T03:15:01.419Z (3 months ago)
- Topics: inter-property-constraints, json-schema, json-schema-form, json-schema-forms, validation-rules
- Language: JavaScript
- Homepage: https://gbroques.github.io/json-schema-interproperty-expressions/
- Size: 126 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# JSON Schema Interproperty Expressions
**Motivation:** [JSON Schema](https://json-schema.org/) provides a comprehensive [vocabulary](https://json-schema.org/learn/glossary.html#vocabulary) for property-level constraints, but lacks a vocabulary for [relational constraints](https://en.wikipedia.org/wiki/Relational_operator) *between* properties.
Simple use-cases for interproperty expressions are:
* ensuring an end date is after a start date
expand schema```js
{
"type": "object",
"properties": {
"startDate": {
"type": "string",
"format": "date",
"title": "Start Date"
},
"endDate": {
"type": "string",
"format": "date",
"title": "End Date"
}
},
"interpropertyExpressions": [
{
// Equivalent infix expression:
// {startDate} < {endDate}
"expression": "{startDate} {endDate} <",
"type": "postfix",
"message": "End date must be after start date.",
"properties": ["startDate", "endDate"]
}
]
}
```
* ensuring a confirmation password is the same as a password
expand schema```js
{
"type": "object",
"properties": {
"password": {
"type": "string",
"title": "Password"
},
"confirmationPassword": {
"type": "string",
"title": "Confirm Password"
}
},
"interpropertyExpressions": [
{
// Equivalent infix expression:
// {password} = {confirmationPassword}
"expression": "{password} {confirmationPassword} =",
"type": "postfix",
"message": "Confirmation password must match password.",
"properties": ["password", "confirmationPassword"]
}
]
}
```
This repository features an advanced [CAD](https://en.wikipedia.org/wiki/Computer-aided_design) example where the user inputs values defining the [hub](https://en.wikipedia.org/wiki/Wheel#Hub) and [rotor](https://en.wikipedia.org/wiki/Rotor_(electric)) for an [electric generator](https://en.wikipedia.org/wiki/Electric_generator).
To run the demo:
1. Install dependencies (requires [Node.js](https://nodejs.org/en)).
npm install
2. Start local HTTP server.
npm start
The demo uses a [postfix expression](https://en.wikipedia.org/wiki/Reverse_Polish_notation), as it's easy to evaluate using a [stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)), and avoids the use of [`eval`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) which poses security risks.
(⚠️ *Edge cases are not tested.*)
The below **GIF** demonstrates validating the complex relationship between three related inputs explained by the **Diagram**.
The user can adjust any of the three inputs when the constraint is violated.
|GIF|Diagram|
|---|---|
|![Demo](./json-schema-interproperty-expressions-demo.gif)|![Diagram](./diagram.svg)|[`diagram.drawio`](./diagram.drawio) may be edited at https://app.diagrams.net/
## interpropertyExpressions keyword
The `interpropertyExpressions` [keyword](https://json-schema.org/learn/glossary.html#keyword) **MUST** be included alongside the schema of an object.
For example:
```js
{
"type": "object",
"properties": {
// ...
},
"interpropertyExpressions": [
// ...
]
}
````interpropertyExpressions` includes an array of `InterpropertyExpression` objects whose schema is defined by the following [meta-schema](https://json-schema.org/learn/glossary.html#meta-schema):
```js
{
"type": "object",
"title": "InterpropertyExpression object",
"properties": {
"expression": {
"type": "string",
"description": "Relational expression between two or more properties where true means valid."
},
"type": {
"type": "string",
"description": "Type of expression. Implementing libraries may only support one or more types.",
"enum": ["postfix", "infix", "prefix"]
},
"message": {
"type": "string",
"description": "Message to display if expression evaluates to false."
},
"properties": {
"type": "array",
"description": "Array of property names included in expression.",
"items": {
"type": "string",
"description": "Property name with dot notation for nested properties."
}
}
}
}
```### Postfix Expression
An expression where [operators](https://en.wikipedia.org/wiki/Operation_(mathematics)) follow [operands](https://en.wikipedia.org/wiki/Operand) meeting the following criteria:
* Operators and operands are delimited by white-space.
Rationale
Avoids ambiguity in parsing expressions where operands contain potential operators.For example, consider the following expression comparing two dates:
```
2022-12-25 2022-12-26 <
```Then the following expression subtracting two numbers:
```
2022 12 -
```Other examples include timestamps (e.g. `2018-11-13T20:20:39+00:00`) and addition (i.e. `+`).
* Operators have a fixed number of operands.
Rationale
If every operator has a fixed number of operands, then parentheses are not needed.
* Operators are one symbol.
RationaleAvoids a [lookahead](https://en.wikipedia.org/wiki/Parsing#Lookahead) when parsing potentially ambiguous operators such as `<` (if `<=` is also an operator).
* Properties are surround by curly-braces (i.e. `{` and `}`) with dot notation for nested properties.
The following table documents supported [**arithmetic** operators](https://en.wikipedia.org/wiki/Arithmetic).
|Operator|Name|Operands|
|:------:|----|:------:|
|`+`|[Addition](https://en.wikipedia.org/wiki/Addition)|2|
|`-`|[Subtraction](https://en.wikipedia.org/wiki/Subtraction)|2|
|`*`|[Multiplication](https://en.wikipedia.org/wiki/Multiplication)|2|
|`/`|[Division](https://en.wikipedia.org/wiki/Division_(mathematics))|2|
|`^`|[Exponentiation](https://en.wikipedia.org/wiki/Exponentiation)|2|
|`%`|[Modulo](https://en.wikipedia.org/wiki/Modulo)|2|The following table documents supported [**relational** operators](https://en.wikipedia.org/wiki/Relational_operator).
|Operator|Name|Operands|
|:------:|----|:------:|
|`<`|Less than|2|
|`≤`|Less than or equal to|2|
|`>`|Greater than|2|
|`≥`|Greater than or equal to|2|
|`=`|Equal to|2|
|`≠`|Not equal to|2|## Related Work
According to "*[A Catalogue of Inter-parameter Dependencies in RESTful Web APIs](https://www.researchgate.net/publication/336816181_A_Catalogue_of_Inter-parameter_Dependencies_in_RESTful_Web_APIs)*", "Arithmetic / Relational" dependencies between parameters are the most recurrent across the APIs examined. Additionally, 17% of the inter-parameter dependencies
found are of this type.[![Frequency of the dependencies according to the number of occurrences and the number of APIs (out of 40) presenting them.](inter-parameter-dependencies-in-webapis.webp)](https://medium.com/isa-group/inter-parameter-dependencies-in-rest-apis-4664e901c124)