OpenAPI extension
I'd like to add OpenAPI extensions to endpoints, especially for GPTs Actions.
Example
/api/some/resource:
get:
operationId: blah
x-openai-isConsequential: false
post:
operationId: blah2
x-openai-isConsequential: true
I want to discuss:
1. The encoding of extension values
The spec says:
The extension value can be a primitive, an array, an object or null.
Possible types are:
- zio.schema.DynamicValue
- zio.json.ast.Json
- Dedicated AST
Personally I'd prefer Json AST, because it is:
- Isomorphic to the spec
- Easy for users to build
- Already has its own schema
2. Schema derivation
As the extensions should be serialized at the same level as the predefined fields, automatic schema derivation won't work out-of-box.
A solution I thought is to add a transient field and wrap the derived schema with DynamicValue.
case class Foo(
a: Int,
b: String,
@transientField
extensions: ListMap[String, Json] = ListMap.empty
) {
def withExtensions(newExtensions: ListMap[String, Json]): Foo = copy(extensions = newExtensions)
}
object Foo {
private val baseSchema = DeriveSchema.gen[Foo]
given Schema[Foo] =
Schema.dynamicValue.transformOrFail( dv =>
baseSchema.gen[Foo].fromDynamic(dv).map { foo =>
val ex = ??? // fields with "x-" keys from the DynamicValue
foo.withExtensions(ex)
},
foo => baseSchema.toDynamic(foo) // and then merge extensions
)
}
What do you think?
@987Nabil What do you think?
https://scastie.scala-lang.org/guersam/h1kyN8o8TNiZ9kpXVByPRg/54
Did a quick sketch. Although it worked with the most basic example, it failed with Enumeration, Dictionary and Tuple fields because JsonCodec[DynamicValue] doesn't support them in direct mapping mode.
For this approach, a tolerant mode for Schema[DynamicValue] might be needed but I'm not sure if it's possible.
I'll take a look at this. But I have some other priorities. So it might take a week or two. I can't say how to solve this without some research.
@987Nabil Thanks. Now I have more urgent issues to adopt endpoint DSL. I'll report them soon.