guardrail icon indicating copy to clipboard operation
guardrail copied to clipboard

Support for Any Type property in schema

Open justcoon opened this issue 3 years ago • 0 comments

Open Api Specification mentioning Any Type

based on that i tried to define

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

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

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

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

case class EntityWithProp(id: String, name: String, prop:  io.circe.Json)

what do you think about that?

thank you for your response

Peter

justcoon avatar Jun 30 '21 14:06 justcoon