guardrail-dev / guardrail-dev/guardrail
Support for Any Type property in schema
- Dominant language
- Scala
- Stars
- 541
- Forks
- 138
- PR merge metrics
- No merged PRs in 30d
Description
[Open Api Specification](https://swagger.io/docs/specification/data-models/data-types/) mentioning Any Type
based on that i tried to define
``` yaml
EntityWithProp:
type: object
properties:
id:
type: string
name:
type: string
prop:
anyOf:
- type: string
- type: number
- type: integer
- type: boolean
- type: array
items: { }
- type: object
description: 'Can be anything: string, number, array, object, etc.'
x-scala-type: io.circe.Json
required:
- id
- name
- prop
```
but code generator will produce
```scala
case class EntityWithProp(id: String, name: String, prop: EntityWithProp.Prop)
object EntityWithProp {
implicit val encodeEntityWithProp: Encoder.AsObject[EntityWithProp] = {
val readOnlyKeys = Set[String]()
Encoder.AsObject.instance[EntityWithProp](a => JsonObject.fromIterable(Vector(("id", a.id.asJson), ("name", a.name.asJson), ("prop", a.prop.asJson)))).mapJsonObject(_.filterKeys(key => !(readOnlyKeys contains key)))
}
implicit val decodeEntityWithProp: Decoder[EntityWithProp] = new Decoder[EntityWithProp] { final def apply(c: HCursor): Decoder.Result[EntityWithProp] = for (v0 <- c.downField("id").as[String]; v1 <- c.downField("name").as[String]; v2 <- c.downField("prop").as[EntityWithProp.Prop]) yield EntityWithProp(v0, v1, v2) }
}
```
where EntityWithProp.Prop is missing (probably this is because anyOf is not supported in this generator)
in compare schema with dictionary
```yaml
EntityWithProps:
type: object
properties:
id:
type: string
name:
type: string
props:
type: object
additionalProperties: true # anyval for value
required:
- id
- name
- props
```
is generated without issues
```scala
case class EntityWithProps(id: String, name: String, props: Map[String, io.circe.Json] = Map.empty)
object EntityWithProps {
implicit val encodeEntityWithProps: Encoder.AsObject[EntityWithProps] = {
val readOnlyKeys = Set[String]()
Encoder.AsObject.instance[EntityWithProps](a => JsonObject.fromIterable(Vector(("id", a.id.asJson), ("name", a.name.asJson), ("props", a.props.asJson)))).mapJsonObject(_.filterKeys(key => !(readOnlyKeys contains key)))
}
implicit val decodeEntityWithProps: Decoder[EntityWithProps] = new Decoder[EntityWithProps] { final def apply(c: HCursor): Decoder.Result[EntityWithProps] = for (v0 <- c.downField("id").as[String]; v1 <- c.downField("name").as[String]; v2 <- c.downField("props").as[Map[String, io.circe.Json]]) yield EntityWithProps(v0, v1, v2) }
}
```
in case of EntityWithProp, i think it should be similar, and generated code should be like
```scala
case class EntityWithProp(id: String, name: String, prop: io.circe.Json)
```
what do you think about that?
thank you for your response
Peter
Contributor guide
Research direction
The issue names no source file or test; start by tracing how the generator handles the shown anyOf schema and compare it with the working additionalProperties case. Done means the EntityWithProp example generates prop as io.circe.Json with corresponding encoding and decoding.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- openapi, scala
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100