Skip to content

OneOf enlightenment needed #730

@burgesQ

Description

@burgesQ

Hi, I'm trying to "fully" support an endpoint that may return a "OneOf" equivalent as response body.

I've looked a bit around the github, found some issue and a nice example - but they're a few limitations I've faced afterward:

  1. the response payload miss the "$schema" field
response example
╰─  16:10:01 ❯ http :8888/greeting/oneof                                                                                   ─╯
HTTP/1.1 200 OK
Content-Length: 28
Content-Type: application/json
Date: Mon, 17 Feb 2025 15:10:01 GMT

{
    "message": "Hello, oneof!"
}
2) the swagger UI poorly support the `oneOf` schema: 2.a) response example isn't dynamically reloaded on schema change 2.b) schema selection doesn't allow nicer documentation

I've found some weird ways of "fixing" my issues, and I'd like help to get from "weird ways" to "expected ways" 🙈

I ended with the following piece of code to fix my issue 1 and 2.b:

diff to the example
--- example.go	2025-02-17 16:14:55.593638808 +0100
+++ mod_1.go	2025-02-17 16:14:38.690559026 +0100
@@ -57,10 +57,12 @@
 
 		// Create a schema for the output body.
 		registry := api.OpenAPI().Components.Schemas
+
+		schNew := registry.Schema(reflect.TypeOf(GreetingBody{}), true, "")
+		schOld := registry.Schema(reflect.TypeOf(GreetingBodyOld{}), true, "")
 		schema := &huma.Schema{
 			OneOf: []*huma.Schema{
-				registry.Schema(reflect.TypeOf(GreetingBody{}), true, ""),
-				registry.Schema(reflect.TypeOf(GreetingBodyOld{}), true, ""),
+				schNew, schOld,
 			},
 		}
 
@@ -76,6 +78,8 @@
 						"application/json": {
 							Schema: schema,
 						},
+						"old": {Schema: schOld},
+						"new": {Schema: schNew},
 					},
 				},
 			},
  • 1: for some reason, referencing schOld and schNew as schema "as is" to a referenced huma.MediaType enable the magic that inject the $schema field in response of these struct
new response example
╰─  16:36:46 ✘ 1 ❯ http :8888/greeting/oneof                                                                               ─╯
HTTP/1.1 200 OK
Content-Length: 88
Content-Type: application/json
Date: Mon, 17 Feb 2025 15:36:46 GMT
Link: </schemas/GreetingBody.json>; rel="describedBy"

{
    "$schema": "http://localhost:8888/schemas/GreetingBody.json",
    "message": "Hello, oneof!"
}
  • 2.b: the "old" and "new" key now exist in the UI, allowing me to inject more "context as doc"
Swagger UI screenshot

Image

Little detours, If I now select the "old" or "new" content type in the swagger UI, the example is now cleared. As a "fix" I'm currently setting my MediaType.Example to some matching, json.RawMessage, but I would prefer for it to be auto-generated like usual response schema.

Regarding 2.a; I still haven't found a solution, so currently I have to access docs#/schemas/GreetingBodyOld to obtain a full doc of my response.

nb:\

  • issue 1 isn't that much of an issue, just my PTSD.\
  • issue 2.a shall probably be opened on the swagger UI repo aka https://github.com/stoplightio/elements.\
  • issue 2.b probably has no solution as of today ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions