fix(entoas): example annotation
Summary
I found an issue with ent and entoas. While checking out a generated openapi.json file I thought it would be nice to have some example values prepared for testing the API.
Description
By browsing the entoas's source code, I found annotations for that [entoas.Example] ready to use:https://github.com/ent/contrib/blob/d262910a1bbd19484e3d449ec7e41f78c8f5f401/entoas/annotation.go#L75
After playing with it for some time, even if it provided examples, it seems that is completely ignored.
Current behaviour
I was adding them like this:
field.String("name").
Annotations(entoas.Example("zxc")),
In very different scenarios - on fields, edges, and top-level annotations nothing changed. The spec still looks like this
{
"summary": "Create a new User",
"description": "Creates a new User and persists it to storage.",
"operationId": "createUser",
"requestBody": {
"description": "User to create",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}
}
}
Root cause
After, some debugging, I found out that there is no code responsible for that. So here I am.
The main problem is in the OgenSchema function. It gets a schema for each field type (f.Type.String()) and returns it without any changes - e.g. "string" -> ogen.String(). Anything else is basically ignored.
Fix & changes
After changing if-logic to switch-logic in the generator.go file it only required adding a quick fix:
if ant.Example != nil {
jv, err := json.Marshal(ant.Example)
if err != nil {
return nil, fmt.Errorf("cannot marshal example annotation for field %s", f.Name)
}
schema.Example = jv
}
But it came out there was another problem underlying with the types maps. In the upstream, it holds pointers to ogen's schemas so any change which is done on the schema is being propagated to the other fields. My solution for this is a function with a switch statement
(func types(t string) *ogen.Schema {
switch t {
case "bool":
return ogen.Bool()
case "time.Time":
return ogen.DateTime()
case "string":
return ogen.String()
case "[]byte":
return ogen.Bytes()
case "uuid.UUID":
return ogen.UUID()
// ....
For the sake of being future-proof, I also added a unit test that covers that case (func TestOgenSchema_Example(t *testing.T)
@a8m @masseelch any updates on this? just a simple feature
I am trying to add examples with entoas.Example() annotation and found it doesn't work at all. I stumbled across this pull request and #577 that sadly have no updates from the maintainers. Thank you for your contribution. Hope this can be merged soon.