swift-openapi-generator icon indicating copy to clipboard operation
swift-openapi-generator copied to clipboard

Support `type: 'null'` with anyOf and oneOf

Open dpasirst opened this issue 3 months ago • 2 comments

Motivation

Summary

This PR takes a different approach than the prior PRs mentioned below. It attempts to implement what @czechboy0 suggested by filtering/modifying the initial parsed openapi document at a point where nullablity can be handled and before the rest of the generator kicks in to begin producing an output.

Background

swift-openapi-generator does not "support" type: 'null' when used with anyOf and oneOf. The problem became worse after with yams >=5.1. There are multiple issues filed on and related to this topic: https://github.com/apple/swift-openapi-generator/issues/817 https://github.com/apple/swift-openapi-generator/issues/419 https://github.com/apple/swift-openapi-generator/issues/565 https://github.com/apple/swift-openapi-generator/issues/513 https://github.com/apple/swift-openapi-generator/issues/286

There are also older PRs from @brandonbloom: https://github.com/apple/swift-openapi-generator/pull/557 https://github.com/apple/swift-openapi-generator/pull/558 But it seems not to be moving forward.

When looking over these issues I have seen:

  1. @czechboy0 suggesting to modify the openapi document by removing the { "type": "null" } from the anyOf and oneOf definitions. This is great if you are starting by defining your own OpenAPI document, but manually doing so is not maintainable when the document is generated and provided to you with regular updates.
  2. In the PRs from @brandonbloom, there were challenges and suggestions highlighted a) @czechboy0 suggested filtering out null https://github.com/apple/swift-openapi-generator/pull/557#issuecomment-2034640640 b) @czechboy0 also called out that simply removing the null would be losy https://github.com/apple/swift-openapi-generator/pull/558#issuecomment-2034319168. In this case, we end up with the field being treated as required instead of optional. c) it needs to work for both any/oneOf { $ref ..., null} and cases with { $ref ..., $ref ..., null} https://github.com/apple/swift-openapi-generator/pull/558#issuecomment-2033739878

Modifications

  1. Modified Sources / _OpenAPIGeneratorCore / GeneratorPipline.swift by adding several extensions to perform the schema filtering of null from anyOf and oneOf and if null is found, it marks the in memory schema context as nullable for that field.
  2. Added Tests to SnippetBasedReferenceTests
  3. Modified SnippetBasedReferenceTests for makeTypesTranslator() to either removingNullFromAnyOfAndOneOf() or sanitizeSchemaNulls(document) to approximate processing that a file read and processed via GeneratorPipline would pass through.

Result

The resulting generated code seems to behave as expected.

Test Plan

Tests added to snippets, snippets modified to call the same function(s) used in the GeneratorPipeline.

dpasirst avatar Sep 25 '25 17:09 dpasirst

removed "WIP" from the title. I think it is ready for a real review.

dpasirst avatar Sep 30 '25 14:09 dpasirst

Thanks @dpasirst - just a heads up that it'll take me some time to properly review, as once we make this change, it'd be a breaking change to revert it. I also want to see if the new OpenAPI versions 3.2.0 and 3.1.2 offer further clarification about semantics related to nullable values.

czechboy0 avatar Oct 06 '25 10:10 czechboy0