Skip to content

Support F# option type in OpenApi schema generator #59528

@Lanayx

Description

@Lanayx

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

OpenAPI support has recently been added in several F# web frameworks (Oxpecker, Giraffe, Falco). However there is a problem, that F# option type is not respected well. Here is an example with Oxpecker:

open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Http
open Microsoft.Extensions.DependencyInjection
open Oxpecker
open Oxpecker.OpenApi

type MyModel = { Name: string; Age: int option }

let endpoints = GET [
    route "/myModel" <| %TypedResults.Ok { Name = "John"; Age = None }
        |> configureEndpoint _.WithName("MyModel")
        |> addOpenApiSimple<unit, MyModel>
]

[<EntryPoint>]
let main args =
    let builder = WebApplication.CreateBuilder(args)
    builder.Services.AddRouting().AddOxpecker().AddOpenApi() |> ignore
    let app = builder.Build()
    app.UseRouting().UseOxpecker(endpoints) |> ignore
    app.MapOpenApi() |> ignore
    app.Run()
    0 // Exit code

Generates the following schema:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Empty | v1",
    "version": "1.0.0"
  },
  "paths": {
    "/myModel": {
      "get": {
        "tags": [
          "Empty"
        ],
        "operationId": "MyModel",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyModel"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "FSharpOptionOfint": {
        "pattern": "^-?(?:0|[1-9]\\d*)$",
        "type": "integer"
      },
      "MyModel": {
        "required": [
          "name",
          "age"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "$ref": "#/components/schemas/FSharpOptionOfint"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Empty"
    }
  ]
}

Describe the solution you'd like

I expect it to generate the same schema as with just int, but without making this field required:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Empty | v1",
    "version": "1.0.0"
  },
  "paths": {
    "/myModel": {
      "get": {
        "tags": [
          "Empty"
        ],
        "operationId": "MyModel",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyModel"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "MyModel": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "integer",
            "format": "int32"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Empty"
    }
  ]
}

Additional context

Note that FSharp option is already respected by System.Text.Json.

ValueOption type should also be supported in the same way.

.NET SDK:
 Version:           9.0.101
 Commit:            eedb237549
 Workload version:  9.0.100-manifests.4a280210
 MSBuild version:   17.12.12+1cce77968

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapi

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions