dotnet / dotnet/aspnetcore

Support F# option type in OpenApi schema generator

Open
#59,528 10 comments 43 reactions 0 assignees View on GitHub
area-minimal feature-openapi
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [x] 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:

```fsharp
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
]

[]
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:
```json
{
"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:
```json
{
"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](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/FSharp/FSharpOptionConverter.cs) 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
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.