OpenAPI spec to endpoint generator does not recognize field validation
Is your feature request related to a problem? Please describe.
The code that gets generated based on an openapi spec does not take into account additional field validations, for example, for the following definition
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string",
"minLength": 3
},
"tag": {
"type": "string"
}
}
}
}
and the endpoint using it
"paths": {
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
the case class that gets generated looks like this
case class Pet(
id: Long,
name: String,
tag: Option[String]
)
running a server with a dummy implementation
val httpApp = Pets.createPets.implement(Handler.fromFunctionZIO(pet => {ZIO.logInfo("Pet: " + pet.toString)})).toHttpApp
Server.serve(httpApp)
and issuing a POST request against /pets with payload that should fail validation (the name size should be at least 3 character long)
{
"id":1,
"name": "n"
}
gets processed successfully instead
Describe the solution you'd like
changing the generated case class to include zio-schema validations seems to work with no changes to other parts of the generated code
case class Pet(
id: Long,
@validate(Validation.minLength(3))
name: String,
tag: Option[String]
)
in the corresponding endpoint definition
val createPets=Endpoint(Method.POST / "pets")
.in[Pet]
.out[Unit](status = Status.Created)
}
.in[Pet] already responsible for validating input against the schema, and after adding the validation annotation I'm now getting 400 response from the server,
However the response body is empty which could be a problem.
Describe alternatives you've considered An alternative could be to generate endpoints that return Either[ValidationError, T] for users to implement and adjust format of validation errors if needed
Additional context the full example https://github.com/stanislav-chetvertkov/zio-http-gen-example
Your described solution should be the right way. However, I am not sure that all Open API validations can be mapped to current schema validations. It might need some extension of zio schema. This would need to be checked
/bounty $250
💎 $250 bounty • ZIO
Steps to solve:
- Start working: Comment
/attempt #2786with your implementation plan - Submit work: Create a pull request including
/claim #2786in the PR body to claim the bounty - Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts
Thank you for contributing to zio/zio-http!
Add a bounty • Share on socials
| Attempt | Started (GMT+0) | Solution |
|---|---|---|
| 🔴 @stanislav-chetvertkov | Jun 8, 2024, 11:39:56 AM | WIP |
| 🟢 @987Nabil | #2968 |
I got a bit stuck with adding more validation parameters when parsing openapi schemas
@nowarn("msg=possible missing interpolator")
private[openapi] case class SerializableJsonSchema(
@fieldName("$ref") ref: Option[String] = None,
@fieldName("type") schemaType: Option[TypeOrTypes] = None,
format: Option[String] = None,
oneOf: Option[Chunk[SerializableJsonSchema]] = None,
allOf: Option[Chunk[SerializableJsonSchema]] = None,
anyOf: Option[Chunk[SerializableJsonSchema]] = None,
@fieldName("enum") enumValues: Option[Chunk[Json]] = None,
properties: Option[Map[String, SerializableJsonSchema]] = None,
additionalProperties: Option[BoolOrSchema] = None,
required: Option[Chunk[String]] = None,
items: Option[SerializableJsonSchema] = None,
nullable: Option[Boolean] = None,
description: Option[String] = None,
example: Option[Json] = None,
examples: Option[Chunk[Json]] = None,
discriminator: Option[OpenAPI.Discriminator] = None,
deprecated: Option[Boolean] = None,
contentEncoding: Option[String] = None,
contentMediaType: Option[String] = None,
default: Option[Json] = None,
pattern: Option[String] = None,
minimum: Option[Double] = None,
maximum: Option[Double] = None,
)
First, I added minimum: Option[Double] = None, and everything worked and propagated without issues. However, when I added the second field maximum: Option[Double] = None, I started getting the following error:
.components.schemas.Pet(none of the subtypes could decode the data)
It looks like the error is coming from zio-schema and has something to do with the 22 field restriction, with the last added field being the 23rd.
I'll try to look for a workaround, maybe there is an hlist based approach or schema declarations could be rearranged.
might be a bug - I was able to reproduce it in a simplified form https://github.com/zio/zio-schema/issues/691
I am done with the impl. But another fix for zio-schema is needed https://github.com/zio/zio-schema/pull/698
💡 @987Nabil submitted a pull request that claims the bounty. You can visit your bounty board to reward.