{"id":19974283,"url":"https://github.com/gbroques/json-schema-interproperty-expressions","last_synced_at":"2026-05-12T18:05:22.546Z","repository":{"id":169517190,"uuid":"645505551","full_name":"gbroques/json-schema-interproperty-expressions","owner":"gbroques","description":"JSON Schema extension for arithmetic and relational constraints between properties.","archived":false,"fork":false,"pushed_at":"2023-05-26T18:07:53.000Z","size":129,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-12T09:42:18.115Z","etag":null,"topics":["inter-property-constraints","json-schema","json-schema-form","json-schema-forms","validation-rules"],"latest_commit_sha":null,"homepage":"https://gbroques.github.io/json-schema-interproperty-expressions/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gbroques.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-25T20:08:09.000Z","updated_at":"2023-05-26T17:23:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"a03908a9-3db7-4dbf-92ff-a27c316c8eee","html_url":"https://github.com/gbroques/json-schema-interproperty-expressions","commit_stats":null,"previous_names":["gbroques/json-schema-interproperty-expressions"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fjson-schema-interproperty-expressions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fjson-schema-interproperty-expressions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fjson-schema-interproperty-expressions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbroques%2Fjson-schema-interproperty-expressions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gbroques","download_url":"https://codeload.github.com/gbroques/json-schema-interproperty-expressions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241411427,"owners_count":19958746,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["inter-property-constraints","json-schema","json-schema-form","json-schema-forms","validation-rules"],"created_at":"2024-11-13T03:14:31.628Z","updated_at":"2026-05-12T18:05:17.500Z","avatar_url":"https://github.com/gbroques.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JSON Schema Interproperty Expressions\n\n**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.\n\nSimple use-cases for interproperty expressions are:\n\n* ensuring an end date is after a start date\n  \n  \u003cdetails\u003e\n    \u003csummary\u003eexpand schema\u003c/summary\u003e\n\n    ```js\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"startDate\": {\n          \"type\": \"string\",\n          \"format\": \"date\",\n          \"title\": \"Start Date\"\n        },\n        \"endDate\": {\n          \"type\": \"string\",\n          \"format\": \"date\",\n          \"title\": \"End Date\"\n        }\n      },\n      \"interpropertyExpressions\": [\n        {\n          // Equivalent infix expression:\n          // {startDate} \u003c {endDate}\n          \"expression\": \"{startDate} {endDate} \u003c\",\n          \"type\": \"postfix\",\n          \"message\": \"End date must be after start date.\",\n          \"properties\": [\"startDate\", \"endDate\"]\n        }\n      ]\n    }\n    ```\n  \u003c/details\u003e\n\n* ensuring a confirmation password is the same as a password\n\n  \u003cdetails\u003e\n    \u003csummary\u003eexpand schema\u003c/summary\u003e\n\n    ```js\n    {\n      \"type\": \"object\",\n      \"properties\": {\n        \"password\": {\n          \"type\": \"string\",\n          \"title\": \"Password\"\n        },\n        \"confirmationPassword\": {\n          \"type\": \"string\",\n          \"title\": \"Confirm Password\"\n        }\n      },\n      \"interpropertyExpressions\": [\n        {\n          // Equivalent infix expression:\n          // {password} = {confirmationPassword}\n          \"expression\": \"{password} {confirmationPassword} =\",\n          \"type\": \"postfix\",\n          \"message\": \"Confirmation password must match password.\",\n          \"properties\": [\"password\", \"confirmationPassword\"]\n        }\n      ]\n    }\n    ```\n  \u003c/details\u003e\n\nThis 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).\n\nTo run the demo:\n\n1. Install dependencies (requires [Node.js](https://nodejs.org/en)).\n\n       npm install\n\n2. Start local HTTP server.\n\n       npm start\n\nThe 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.\n\n(⚠️ *Edge cases are not tested.*)\n\nThe below **GIF** demonstrates validating the complex relationship between three related inputs explained by the **Diagram**.\n\nThe user can adjust any of the three inputs when the constraint is violated.\n\n|GIF|Diagram|\n|---|---|\n|![Demo](./json-schema-interproperty-expressions-demo.gif)|![Diagram](./diagram.svg)|\n\n[`diagram.drawio`](./diagram.drawio) may be edited at https://app.diagrams.net/\n\n## interpropertyExpressions keyword\n\nThe `interpropertyExpressions` [keyword](https://json-schema.org/learn/glossary.html#keyword) **MUST** be included alongside the schema of an object.\n\nFor example:\n\n```js\n{\n  \"type\": \"object\",\n  \"properties\": {\n    // ...\n  },\n  \"interpropertyExpressions\": [\n    // ...\n  ]\n}\n```\n\n`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):\n\n```js\n{\n  \"type\": \"object\",\n  \"title\": \"InterpropertyExpression object\",\n  \"properties\": {\n    \"expression\": {\n      \"type\": \"string\",\n      \"description\": \"Relational expression between two or more properties where true means valid.\"\n    },\n    \"type\": {\n      \"type\": \"string\",\n      \"description\": \"Type of expression. Implementing libraries may only support one or more types.\",\n      \"enum\": [\"postfix\", \"infix\", \"prefix\"]\n    },\n    \"message\": {\n      \"type\": \"string\",\n      \"description\": \"Message to display if expression evaluates to false.\"\n    },\n    \"properties\": {\n      \"type\": \"array\",\n      \"description\": \"Array of property names included in expression.\",\n      \"items\": {\n        \"type\": \"string\",\n        \"description\": \"Property name with dot notation for nested properties.\"\n      }\n    }\n  }\n}\n```\n\n### Postfix Expression\n\nAn expression where [operators](https://en.wikipedia.org/wiki/Operation_(mathematics)) follow [operands](https://en.wikipedia.org/wiki/Operand) meeting the following criteria:\n\n* Operators and operands are delimited by white-space.\n\n  \u003cdetails\u003e\n    \u003csummary\u003eRationale\u003c/summary\u003e\n    Avoids ambiguity in parsing expressions where operands contain potential operators.\n\n    For example, consider the following expression comparing two dates:\n    ```\n    2022-12-25 2022-12-26 \u003c\n    ```\n\n    Then the following expression subtracting two numbers:\n    ```\n    2022 12 -\n    ```\n\n    Other examples include timestamps (e.g. `2018-11-13T20:20:39+00:00`) and addition (i.e. `+`).\n  \u003c/details\u003e\n\n* Operators have a fixed number of operands.\n\n  \u003cdetails\u003e\n    \u003csummary\u003eRationale\u003c/summary\u003e\n    If every operator has a fixed number of operands, then parentheses are not needed.\n  \u003c/details\u003e\n\n* Operators are one symbol.\n  \u003cdetails\u003e\n    \u003csummary\u003eRationale\u003c/summary\u003e\n\n    Avoids a [lookahead](https://en.wikipedia.org/wiki/Parsing#Lookahead) when parsing potentially ambiguous operators such as `\u003c` (if `\u003c=` is also an operator).\n  \u003c/details\u003e\n\n* Properties are surround by curly-braces (i.e. `{` and `}`) with dot notation for nested properties.\n\nThe following table documents supported [**arithmetic** operators](https://en.wikipedia.org/wiki/Arithmetic).\n\n|Operator|Name|Operands|\n|:------:|----|:------:|\n|`+`|[Addition](https://en.wikipedia.org/wiki/Addition)|2|\n|`-`|[Subtraction](https://en.wikipedia.org/wiki/Subtraction)|2|\n|`*`|[Multiplication](https://en.wikipedia.org/wiki/Multiplication)|2|\n|`/`|[Division](https://en.wikipedia.org/wiki/Division_(mathematics))|2|\n|`^`|[Exponentiation](https://en.wikipedia.org/wiki/Exponentiation)|2|\n|`%`|[Modulo](https://en.wikipedia.org/wiki/Modulo)|2|\n\nThe following table documents supported [**relational** operators](https://en.wikipedia.org/wiki/Relational_operator).\n\n|Operator|Name|Operands|\n|:------:|----|:------:|\n|`\u003c`|Less than|2|\n|`≤`|Less than or equal to|2|\n|`\u003e`|Greater than|2|\n|`≥`|Greater than or equal to|2|\n|`=`|Equal to|2|\n|`≠`|Not equal to|2|\n\n## Related Work\n\nAccording 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\nfound are of this type.\n\n[![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)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbroques%2Fjson-schema-interproperty-expressions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgbroques%2Fjson-schema-interproperty-expressions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbroques%2Fjson-schema-interproperty-expressions/lists"}