OpenAPI/JsonSchema - use unevaluatedProperties instead of additionalProperties and support setting to false - #5961
Merged
Christopher Radek (chrisradek) merged 6 commits intoFeb 12, 2025
Conversation
added 4 commits
February 10, 2025 14:33
…additionalProperties
…additionalProperties: { not {} }
Collaborator
|
All changed packages have been documented.
Show changes
|
Timothee Guerin (timotheeguerin)
approved these changes
Feb 11, 2025
Collaborator
|
You can try these changes here
|
Co-authored-by: Timothee Guerin <timothee.guerin@outlook.com>
Dmitrii Sedelnikov (dmnorc)
pushed a commit
to dmnorc/typespec
that referenced
this pull request
Feb 18, 2025
…roperties and support setting to false (microsoft#5961) Related to microsoft#3549 This PR does a couple things: ### Json Schema and Open API 3.1 use unevaluatedProperties instead of additionalProperties `unevaluatedProperties` is similar to `additionalProperties` in that it can specify what extra properties are allowed on an object. One key difference from additionalProperties though is that it evaluates properties after any in-place applicators. Practically speaking, this means that it will take into account any properties defined in `allOf` subschemas when validating an object instance, whereas additionalProperties only takes into account properties defined in its containing schema. This is particularly useful when trying to set `additionalProperties` to false on a schema that has sub-schemas. #### Risks Functionally, I don't believe this is a breaking change. Where this _might_ cause problems though is if someone is doing their own processing of the Json Schema or Open API 3.1 output to add `additionalProperties: false` if that field isn't present, since those would now be called `unevaluatedProperties`. ### Open API 3 - support Record\<never\> for additionalProperties: { not: {} } This change brings the Open API 3 (3.0 and 3.1) emitter in line with the Json Schema emitter, which already supports treating `Record<never>` as `additionalProperties: { not: {} }`. `{ not: {} }` is equivalent to the boolean `false` for schemas, so this is the same as supporting `additionalProperties: false`. _Note_: For Open API 3.1 output, `unevaluatedProperties` is emitted instead of `additionalProperties`. For Open API 3.0 output that still relies on `additionalProperties`, there's some additional handling of `model extends` so that any properties that exist on a base model, but not the derived model, are redeclared as `propertyName: {}` in the derived model. Without this, if the base model contains any properties that aren't in the derived model, and the derived model spreads `Record<never>`, that emitted schema will never pass validation on an input. #### Example ```tsp model Widget { id: string; ...Record<never>; } ``` ```json { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string" } }, "unevaluatedProperties": { "not": {} } } ``` ### Followups A separate PR will be created to add an emitter option to JsonSchema/OpenAPI emitters to automatically set `additionalProperties: { not: {} }` on at least leaf schemas. --------- Co-authored-by: Christopher Radek <Christopher.Radek@microsoft.com> Co-authored-by: Timothee Guerin <timothee.guerin@outlook.com>
Closed
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related to #3549
This PR does a couple things:
Json Schema and Open API 3.1 use unevaluatedProperties instead of additionalProperties
unevaluatedPropertiesis similar toadditionalPropertiesin that it can specify what extra properties are allowed on an object. One key difference from additionalProperties though is that it evaluates properties after any in-place applicators. Practically speaking, this means that it will take into account any properties defined inallOfsubschemas when validating an object instance, whereas additionalProperties only takes into account properties defined in its containing schema.This is particularly useful when trying to set
additionalPropertiesto false on a schema that has sub-schemas.Risks
Functionally, I don't believe this is a breaking change. Where this might cause problems though is if someone is doing their own processing of the Json Schema or Open API 3.1 output to add
additionalProperties: falseif that field isn't present, since those would now be calledunevaluatedProperties.Open API 3 - support Record<never> for additionalProperties: { not: {} }
This change brings the Open API 3 (3.0 and 3.1) emitter in line with the Json Schema emitter, which already supports treating
Record<never>asadditionalProperties: { not: {} }.{ not: {} }is equivalent to the booleanfalsefor schemas, so this is the same as supportingadditionalProperties: false.Note: For Open API 3.1 output,
unevaluatedPropertiesis emitted instead ofadditionalProperties.For Open API 3.0 output that still relies on
additionalProperties, there's some additional handling ofmodel extendsso that any properties that exist on a base model, but not the derived model, are redeclared aspropertyName: {}in the derived model. Without this, if the base model contains any properties that aren't in the derived model, and the derived model spreadsRecord<never>, that emitted schema will never pass validation on an input.Example
{ "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string" } }, "unevaluatedProperties": { "not": {} } }Followups
A separate PR will be created to add an emitter option to JsonSchema/OpenAPI emitters to automatically set
additionalProperties: { not: {} }on at least leaf schemas.