Skip to content

Commit 7c13fb3

Browse files
Copilotbaywet
andauthored
fix: implement unevaluatedProperties as schema per JSON Schema 2020-12 (#2728)
* Initial plan * feat: add UnevaluatedPropertiesSchema support to IOpenApiSchema - Create IOpenApiSchemaWithUnevaluatedProperties interface for binary compatibility - Add UnevaluatedPropertiesSchema property to OpenApiSchema - Update OpenApiSchemaReference to implement new interface - Update serialization to handle both boolean and schema cases - Update V31 deserialization to handle both boolean and schema cases - Add comprehensive documentation with TODO markers for next major version Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> * test: add comprehensive tests for UnevaluatedProperties - Add serialization tests for boolean and schema cases - Add deserialization tests for V3.1 - Add copy constructor test - Fix default value to true (allowing unevaluated properties by default) Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> * fix: correct deserialization and test for UnevaluatedPropertiesSchema - Fix deserialization to use ValueNode check like AdditionalProperties - Fix copy constructor test to properly cast before modifying - Update PublicAPI.Unshipped.txt with new API surface - Update global.json to use available SDK version - All UnevaluatedProperties tests now passing Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> * fix: address PR feedback on UnevaluatedProperties implementation - Simplify copy constructor using pattern matching - Add V3.2 deserialization support for UnevaluatedPropertiesSchema - Add test for default value (no property set, defaults to true) - Emit as x-jsonschema-unevaluatedProperties extension for versions < 3.1 - Add comprehensive tests for extension serialization in V2 and V3.0 - Add V3.2 deserialization tests Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> * refactor: use OpenApiConstants for extension name - Added UnevaluatedPropertiesExtension constant to OpenApiConstants - Replaced hardcoded "x-jsonschema-unevaluatedProperties" strings with constant - Updated both V3.0 and V2.0 serialization paths - Updated PublicAPI.Unshipped.txt with new constant Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> * chore: reverts dotnet version change * chore: update benchmark reports Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: baywet <7905502+baywet@users.noreply.github.com> Co-authored-by: Vincent Biret <vibiret@microsoft.com>
1 parent c7f9885 commit 7c13fb3

19 files changed

+675
-142
lines changed
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
```
22
3-
BenchmarkDotNet v0.15.4, Windows 11 (10.0.26200.6899)
4-
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
5-
.NET SDK 8.0.415
6-
[Host] : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4
7-
ShortRun : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4
3+
BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.3 LTS (Noble Numbat)
4+
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
5+
.NET SDK 8.0.417
6+
[Host] : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3
7+
ShortRun : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3
88
99
Job=ShortRun IterationCount=3 LaunchCount=1
1010
WarmupCount=3
1111
1212
```
13-
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated |
14-
|------------- |---------------:|---------------:|--------------:|-----------:|-----------:|----------:|-------------:|
15-
| PetStoreYaml | 913.5 μs | 3,348.1 μs | 183.52 μs | 58.5938 | 11.7188 | - | 361.25 KB |
16-
| PetStoreJson | 425.1 μs | 327.5 μs | 17.95 μs | 35.1563 | 5.8594 | - | 223.39 KB |
17-
| GHESYaml | 1,765,825.8 μs | 5,036,336.6 μs | 276,058.60 μs | 60000.0000 | 23000.0000 | 4000.0000 | 345082.98 KB |
18-
| GHESJson | 848,197.4 μs | 1,381,723.6 μs | 75,736.93 μs | 33000.0000 | 12000.0000 | 2000.0000 | 206597.63 KB |
13+
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated |
14+
|------------- |---------------:|--------------:|------------:|-----------:|-----------:|----------:|------------:|
15+
| PetStoreYaml | 506.2 μs | 95.21 μs | 5.22 μs | 19.5313 | 3.9063 | - | 361.38 KB |
16+
| PetStoreJson | 227.4 μs | 158.42 μs | 8.68 μs | 11.7188 | 1.9531 | - | 223.24 KB |
17+
| GHESYaml | 1,077,570.1 μs | 87,375.79 μs | 4,789.36 μs | 24000.0000 | 19000.0000 | 3000.0000 | 345338.7 KB |
18+
| GHESJson | 478,591.0 μs | 114,328.37 μs | 6,266.72 μs | 13000.0000 | 9000.0000 | 2000.0000 | 206861.5 KB |
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated
2-
PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,913.5 μs,"3,348.1 μs",183.52 μs,58.5938,11.7188,0.0000,361.25 KB
3-
PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,425.1 μs,327.5 μs,17.95 μs,35.1563,5.8594,0.0000,223.39 KB
4-
GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"1,765,825.8 μs","5,036,336.6 μs","276,058.60 μs",60000.0000,23000.0000,4000.0000,345082.98 KB
5-
GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"848,197.4 μs","1,381,723.6 μs","75,736.93 μs",33000.0000,12000.0000,2000.0000,206597.63 KB
2+
PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,506.2 μs,95.21 μs,5.22 μs,19.5313,3.9063,0.0000,361.38 KB
3+
PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,227.4 μs,158.42 μs,8.68 μs,11.7188,1.9531,0.0000,223.24 KB
4+
GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"1,077,570.1 μs","87,375.79 μs","4,789.36 μs",24000.0000,19000.0000,3000.0000,345338.7 KB
5+
GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"478,591.0 μs","114,328.37 μs","6,266.72 μs",13000.0000,9000.0000,2000.0000,206861.5 KB

performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang='en'>
33
<head>
44
<meta charset='utf-8' />
5-
<title>performance.Descriptions-20251024-100447</title>
5+
<title>performance.Descriptions-20260217-210541</title>
66

77
<style type="text/css">
88
table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
@@ -13,23 +13,23 @@
1313
</head>
1414
<body>
1515
<pre><code>
16-
BenchmarkDotNet v0.15.4, Windows 11 (10.0.26200.6899)
17-
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
18-
.NET SDK 8.0.415
19-
[Host] : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4
20-
ShortRun : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4
16+
BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.3 LTS (Noble Numbat)
17+
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
18+
.NET SDK 8.0.417
19+
[Host] : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3
20+
ShortRun : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3
2121
</code></pre>
2222
<pre><code>Job=ShortRun IterationCount=3 LaunchCount=1
2323
WarmupCount=3
2424
</code></pre>
2525

2626
<table>
27-
<thead><tr><th>Method</th><th>Mean </th><th>Error </th><th>StdDev </th><th>Gen0</th><th>Gen1</th><th>Gen2</th><th>Allocated</th>
27+
<thead><tr><th>Method</th><th>Mean </th><th>Error </th><th>StdDev</th><th>Gen0</th><th>Gen1</th><th>Gen2</th><th>Allocated</th>
2828
</tr>
29-
</thead><tbody><tr><td>PetStoreYaml</td><td>913.5 &mu;s</td><td>3,348.1 &mu;s</td><td>183.52 &mu;s</td><td>58.5938</td><td>11.7188</td><td>-</td><td>361.25 KB</td>
30-
</tr><tr><td>PetStoreJson</td><td>425.1 &mu;s</td><td>327.5 &mu;s</td><td>17.95 &mu;s</td><td>35.1563</td><td>5.8594</td><td>-</td><td>223.39 KB</td>
31-
</tr><tr><td>GHESYaml</td><td>1,765,825.8 &mu;s</td><td>5,036,336.6 &mu;s</td><td>276,058.60 &mu;s</td><td>60000.0000</td><td>23000.0000</td><td>4000.0000</td><td>345082.98 KB</td>
32-
</tr><tr><td>GHESJson</td><td>848,197.4 &mu;s</td><td>1,381,723.6 &mu;s</td><td>75,736.93 &mu;s</td><td>33000.0000</td><td>12000.0000</td><td>2000.0000</td><td>206597.63 KB</td>
29+
</thead><tbody><tr><td>PetStoreYaml</td><td>506.2 &mu;s</td><td>95.21 &mu;s</td><td>5.22 &mu;s</td><td>19.5313</td><td>3.9063</td><td>-</td><td>361.38 KB</td>
30+
</tr><tr><td>PetStoreJson</td><td>227.4 &mu;s</td><td>158.42 &mu;s</td><td>8.68 &mu;s</td><td>11.7188</td><td>1.9531</td><td>-</td><td>223.24 KB</td>
31+
</tr><tr><td>GHESYaml</td><td>1,077,570.1 &mu;s</td><td>87,375.79 &mu;s</td><td>4,789.36 &mu;s</td><td>24000.0000</td><td>19000.0000</td><td>3000.0000</td><td>345338.7 KB</td>
32+
</tr><tr><td>GHESJson</td><td>478,591.0 &mu;s</td><td>114,328.37 &mu;s</td><td>6,266.72 &mu;s</td><td>13000.0000</td><td>9000.0000</td><td>2000.0000</td><td>206861.5 KB</td>
3333
</tr></tbody></table>
3434
</body>
3535
</html>

performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
11
```
22
3-
BenchmarkDotNet v0.15.4, Windows 11 (10.0.26200.6899)
4-
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
5-
.NET SDK 8.0.415
6-
[Host] : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4
7-
ShortRun : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4
3+
BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.3 LTS (Noble Numbat)
4+
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
5+
.NET SDK 8.0.417
6+
[Host] : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3
7+
ShortRun : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3
88
99
Job=ShortRun IterationCount=3 LaunchCount=1
1010
WarmupCount=3
1111
1212
```
13-
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
14-
|---------------------------- |-----------:|--------------:|-----------:|-------:|-------:|----------:|
15-
| EmptyApiCallback | 9.857 ns | 9.4413 ns | 0.5175 ns | 0.0051 | - | 32 B |
16-
| EmptyApiComponents | 5.810 ns | 8.1726 ns | 0.4480 ns | 0.0179 | - | 112 B |
17-
| EmptyApiContact | 4.056 ns | 6.2561 ns | 0.3429 ns | 0.0076 | - | 48 B |
18-
| EmptyApiDiscriminator | 3.774 ns | 4.3627 ns | 0.2391 ns | 0.0076 | - | 48 B |
19-
| EmptyDocument | 455.827 ns | 1,324.8541 ns | 72.6197 ns | 0.1822 | 0.0005 | 1144 B |
20-
| EmptyApiEncoding | 4.464 ns | 5.8213 ns | 0.3191 ns | 0.0127 | - | 80 B |
21-
| EmptyApiExample | 4.049 ns | 6.4281 ns | 0.3523 ns | 0.0115 | - | 72 B |
22-
| EmptyApiExternalDocs | 3.554 ns | 9.2144 ns | 0.5051 ns | 0.0064 | - | 40 B |
23-
| EmptyApiHeader | 5.744 ns | 5.7874 ns | 0.3172 ns | 0.0127 | - | 80 B |
24-
| EmptyApiInfo | 4.899 ns | 0.2540 ns | 0.0139 ns | 0.0127 | - | 80 B |
25-
| EmptyApiLicense | 3.276 ns | 5.2349 ns | 0.2869 ns | 0.0076 | - | 48 B |
26-
| EmptyApiLink | 4.808 ns | 5.0966 ns | 0.2794 ns | 0.0115 | - | 72 B |
27-
| EmptyApiMediaType | 5.524 ns | 3.1665 ns | 0.1736 ns | 0.0127 | - | 80 B |
28-
| EmptyApiOAuthFlow | 4.655 ns | 2.4297 ns | 0.1332 ns | 0.0102 | - | 64 B |
29-
| EmptyApiOAuthFlows | 4.611 ns | 2.6531 ns | 0.1454 ns | 0.0102 | - | 64 B |
30-
| EmptyApiOperation | 68.632 ns | 30.0777 ns | 1.6487 ns | 0.0598 | - | 376 B |
31-
| EmptyApiParameter | 5.697 ns | 3.3660 ns | 0.1845 ns | 0.0153 | - | 96 B |
32-
| EmptyApiPathItem | 4.366 ns | 1.1628 ns | 0.0637 ns | 0.0102 | - | 64 B |
33-
| EmptyApiPaths | 56.296 ns | 39.6902 ns | 2.1756 ns | 0.0395 | - | 248 B |
34-
| EmptyApiRequestBody | 3.891 ns | 0.5843 ns | 0.0320 ns | 0.0076 | - | 48 B |
35-
| EmptyApiResponse | 4.411 ns | 1.4575 ns | 0.0799 ns | 0.0102 | - | 64 B |
36-
| EmptyApiResponses | 52.932 ns | 11.5133 ns | 0.6311 ns | 0.0395 | - | 248 B |
37-
| EmptyApiSchema | 15.148 ns | 2.4846 ns | 0.1362 ns | 0.0650 | - | 408 B |
38-
| EmptyApiSecurityRequirement | 12.187 ns | 25.9656 ns | 1.4233 ns | 0.0166 | - | 104 B |
39-
| EmptyApiSecurityScheme | 6.508 ns | 33.8480 ns | 1.8553 ns | 0.0153 | - | 96 B |
40-
| EmptyApiServer | 16.896 ns | 22.6705 ns | 1.2426 ns | 0.0089 | - | 56 B |
41-
| EmptyApiServerVariable | 5.436 ns | 20.6472 ns | 1.1317 ns | 0.0076 | - | 48 B |
42-
| EmptyApiTag | 6.426 ns | 3.3776 ns | 0.1851 ns | 0.0115 | - | 72 B |
13+
| Method | Mean | Error | StdDev | Gen0 | Allocated |
14+
|---------------------------- |-------------:|-----------:|-----------:|-------:|----------:|
15+
| EmptyApiCallback | 12.881 ns | 6.464 ns | 0.3543 ns | 0.0019 | 32 B |
16+
| EmptyApiComponents | 11.115 ns | 8.473 ns | 0.4644 ns | 0.0067 | 112 B |
17+
| EmptyApiContact | 15.612 ns | 43.722 ns | 2.3965 ns | 0.0029 | 48 B |
18+
| EmptyApiDiscriminator | 10.421 ns | 4.157 ns | 0.2278 ns | 0.0029 | 48 B |
19+
| EmptyDocument | 1,552.761 ns | 195.787 ns | 10.7317 ns | 0.0668 | 1144 B |
20+
| EmptyApiEncoding | 12.281 ns | 28.368 ns | 1.5550 ns | 0.0048 | 80 B |
21+
| EmptyApiExample | 12.103 ns | 17.069 ns | 0.9356 ns | 0.0043 | 72 B |
22+
| EmptyApiExternalDocs | 12.684 ns | 83.186 ns | 4.5597 ns | 0.0024 | 40 B |
23+
| EmptyApiHeader | 13.114 ns | 10.617 ns | 0.5819 ns | 0.0048 | 80 B |
24+
| EmptyApiInfo | 17.484 ns | 37.247 ns | 2.0416 ns | 0.0048 | 80 B |
25+
| EmptyApiLicense | 9.304 ns | 4.905 ns | 0.2689 ns | 0.0029 | 48 B |
26+
| EmptyApiLink | 13.260 ns | 7.497 ns | 0.4110 ns | 0.0043 | 72 B |
27+
| EmptyApiMediaType | 13.410 ns | 11.060 ns | 0.6063 ns | 0.0048 | 80 B |
28+
| EmptyApiOAuthFlow | 14.931 ns | 19.265 ns | 1.0560 ns | 0.0038 | 64 B |
29+
| EmptyApiOAuthFlows | 14.980 ns | 13.938 ns | 0.7640 ns | 0.0038 | 64 B |
30+
| EmptyApiOperation | 81.320 ns | 12.915 ns | 0.7079 ns | 0.0224 | 376 B |
31+
| EmptyApiParameter | 13.390 ns | 20.439 ns | 1.1204 ns | 0.0057 | 96 B |
32+
| EmptyApiPathItem | 12.827 ns | 3.747 ns | 0.2054 ns | 0.0038 | 64 B |
33+
| EmptyApiPaths | 64.713 ns | 18.742 ns | 1.0273 ns | 0.0148 | 248 B |
34+
| EmptyApiRequestBody | 14.251 ns | 13.790 ns | 0.7559 ns | 0.0029 | 48 B |
35+
| EmptyApiResponse | 8.811 ns | 3.772 ns | 0.2068 ns | 0.0038 | 64 B |
36+
| EmptyApiResponses | 63.846 ns | 7.887 ns | 0.4323 ns | 0.0148 | 248 B |
37+
| EmptyApiSchema | 26.385 ns | 49.316 ns | 2.7032 ns | 0.0249 | 416 B |
38+
| EmptyApiSecurityRequirement | 17.544 ns | 2.492 ns | 0.1366 ns | 0.0062 | 104 B |
39+
| EmptyApiSecurityScheme | 10.306 ns | 9.709 ns | 0.5322 ns | 0.0057 | 96 B |
40+
| EmptyApiServer | 11.145 ns | 34.746 ns | 1.9045 ns | 0.0033 | 56 B |
41+
| EmptyApiServerVariable | 10.071 ns | 12.498 ns | 0.6850 ns | 0.0029 | 48 B |
42+
| EmptyApiTag | 13.771 ns | 21.097 ns | 1.1564 ns | 0.0043 | 72 B |

0 commit comments

Comments
 (0)