fix(library): serialize additionalProperties schema in OpenAPI V2 documents#2744
fix(library): serialize additionalProperties schema in OpenAPI V2 documents#2744Copilot wants to merge 2 commits intomainmicrosoft/OpenAPI.NET:mainfrom copilot/fix-openapi-schema-issuemicrosoft/OpenAPI.NET:copilot/fix-openapi-schema-issueCopy head branch name to clipboard
Conversation
Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression introduced in v2.3.11 (PR #2630) where additionalProperties with a schema value was silently dropped during OpenAPI v2 serialization, causing information loss for dictionary-type responses (e.g., IDictionary<string, MyModel>). The fix removes an incorrect comment and guard that prevented schema-valued additionalProperties from being serialized, which contradicts the OpenAPI v2.0 specification that supports additionalProperties as either a boolean or a schema object.
Changes:
- Removed incorrect guard preventing schema-valued
additionalPropertiesserialization in V2 - Updated test to reflect correct behavior for empty schema
- Added test case for dictionary-with-$ref scenario
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Microsoft.OpenApi/Models/OpenApiSchema.cs | Fixed SerializeAsV2 method to properly serialize additionalProperties schema, matching V3+ behavior and V2 spec requirements |
| test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs | Renamed test to reflect correct expectation and added new test for dictionary-with-$ref case |
|
Since v2.3.11,
additionalPropertieswith a schema value was silently dropped during OpenAPI v2 serialization, causing information loss for dictionary-type responses (e.g.,IDictionary<string, MyModel>). TheSerializeAsV2method had an incorrect comment "a schema cannot be serialized in v2" — the OpenAPI v2.0 spec does supportadditionalPropertiesas either a boolean or a schema object.Before (broken):
After (correct):
Description
Serialization rules for
additionalPropertiesin V2 (consistent with V3):AdditionalPropertiesschema set → serialize as schema objectAdditionalPropertiesAllowed = false→ serializefalseAdditionalPropertiesAllowed = true(default) → omit (no-op)Type of Change
Related Issue(s)
Changes Made
OpenApiSchema.SerializeAsV2: removed incorrect guard that preventedAdditionalPropertiesschema from being written; addedWriteOptionalObjectcall mirroring the V3 pathSerializeAdditionalPropertiesAsV2DoesNotEmit→SerializeAdditionalPropertiesAsV2WithEmptySchemaEmitswith corrected expectationSerializeAdditionalPropertiesAsV2WithRefSchemaEmitsto cover the dictionary-with-$refcase from the issueTesting
Checklist
Versions applicability
See the contributing guidelines for more information about how patches are applied across multiple versions.
Additional Notes
Regression introduced in PR #2630 which was intended to suppress spurious
additionalProperties: falsein v3.1 but inadvertently also suppressed valid schema-valuedadditionalPropertiesin v2.Original prompt
This section details on the original issue you should resolve
<issue_title>additionalProperties not set in schema for OpenApi V2 documents since v2.3.11, loss of information in things that return dictionaries</issue_title>
<issue_description>Describe the bug
We have some C# code with a schema that returns an IDictionary, where the value is a C# object, e.g.
Our OpenApi generation is configured to set.
We are using OpenApi indirectly via
Swashbuckle.AspNetCore, we picked up the change transitively with an upgrade fromSwashbuckle.AspNetCoreversion10.1.0to10.1.2, which changes the referenced version of Microsoft.OpenApi from 2.3.9 to 2.4.2Expected behavior
With OpenApi 2.3.9, the response looks like this
When browsing using swagger UI, the model is
{ < * >: TestItemResult{ IsMatched: boolean Reason: string } }And the example response is
{ "additionalProp1": { "IsMatched": true, "Reason": "string" }, "additionalProp2": { "IsMatched": true, "Reason": "string" }, "additionalProp3": { "IsMatched": true, "Reason": "string" } }From our perspective these are all correct and expected.
Actual behavior
Since OpenApi 2.3.11, the response looks like this (note additionalProperties missing)
When browsing using swagger UI, the model is
{ }And the example response is
{}Additional context
I looked at the OpenApi release history / changelog, and noted that the change starts with Issue 2619, wherein a user observes "Additional properties false" is incorrectly added to every object in shcema when switching to OpenAPI 3.1
It was then marked fixed in
Looking at the discussion in the issue and PR's, it looks as though the fix was intended to prevent spurious
additionalProperties: falsein v3.It has also removed information from a v2 schema, which doesn't seem to fit with the intent of the bug fix.
If we pick up the new version, our customers will experience this as loss of information/functionality in the swagger document.
Was this loss of information intentional, and if so would it be possible to help us understand why, and/or if there are any changes we can make our our end to work around the issue?
Thank you
</issue_description>
<agent_instructions>follow instructions provided in copilot instructions and contributing.
Look at my reply for the fix that needs to be implemented.
Start by updating unit tests first, then fix the implementation.</agent_instructions>
Comments on the Issue (you are @copilot in this section)
@baywet Hi @borland, Thank you for using the SDK and for reaching out.Yes, the additionalProperties keyword should be serialized the same way across all versions since it's present since OpenAPI v2.0 and defined as a schema or boolean since JSON schema draft 04:
As for deserialization:
Is this something you'd like to submit a pull request for provided some guidance?
Related #2727 #2716</comment_new>
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.