guardrail-dev / guardrail-dev/guardrail

Anonymous enums and object are not generated inside a used discriminant Model

Open
#437 0 comments 0 reactions 0 assignees View on GitHub
bug core help wanted
Dominant language
Scala
Stars
541
Forks
138
PR merge metrics
No merged PRs in 30d

Description

Given this definition

```json
"DiscriminantModel": {
"required": ["type","state", "data"],
"discriminator": "type",
"properties": {
"state": {
"type": "string",
"enum": [
"stateA",
"stateB"
]
},
"type": {
"type": "string"
},
"data": {
"type": "object",
"properties": {
"a": {
"type": "string"
}
}
}
}
}
```

I get this (correct) generated code:

```scala
case class DiscriminantModel(state: DiscriminantModel.State, `type`: String, data: DiscriminantModel.Data)
object DiscriminantModel {
implicit val encodeDiscriminantModel: ObjectEncoder[DiscriminantModel] = {
val readOnlyKeys = Set[String]()
Encoder.forProduct3("state", "type", "data") { (o: DiscriminantModel) => (o.state, o.`type`, o.data) }.mapJsonObject(_.filterKeys(key => !(readOnlyKeys contains key)))
}
implicit val decodeDiscriminantModel: Decoder[DiscriminantModel] = Decoder.forProduct3("state", "type", "data")(DiscriminantModel.apply _)
sealed abstract class State(val value: String) { override def toString: String = value.toString }
object State {
object members {
case object StateA extends State("stateA")
case object StateB extends State("stateB")
}
val StateA: State = members.StateA
val StateB: State = members.StateB
val values = Vector(StateA, StateB)
implicit val encodeState: Encoder[State] = Encoder[String].contramap(_.value)
implicit val decodeState: Decoder[State] = Decoder[String].emap(value => parse(value).toRight(s"$value not a member of State"))
implicit val addPathState: AddPath[State] = AddPath.build(_.value)
implicit val showState: Show[State] = Show.build(_.value)
def parse(value: String): Option[State] = values.find(_.value == value)
}
case class Data(a: Option[String] = None)
object Data {
implicit val encodeData: ObjectEncoder[Data] = {
val readOnlyKeys = Set[String]()
Encoder.forProduct1("a") { (o: Data) => o.a }.mapJsonObject(_.filterKeys(key => !(readOnlyKeys contains key)))
}
implicit val decodeData: Decoder[Data] = Decoder.forProduct1("a")(Data.apply _)
}
}
```

However, if I use this Model in a `allOf` like so:

```json
"ModelA": {
"allOf": [
{
"$ref": "#/definitions/DiscriminantModel"
},
{
"properties": {
"refs": {
```

Then the generated `DiscriminantModel` contains the dispatch code but no more the Anonymous definitions

```scala
trait DiscriminantModel {
def state: String
def data: io.circe.Json
}
object DiscriminantModel {
val discriminator: String = "type"
implicit val encoder: Encoder[DiscriminantModel] = Encoder.instance({
case e: ModelA =>
e.asJsonObject.add(discriminator, "ModelA".asJson).asJson
})
implicit val decoder: Decoder[DiscriminantModel] = Decoder.instance { c =>
val discriminatorCursor = c.downField(discriminator)
discriminatorCursor.as[String].flatMap({
case "ModelA" =>
c.as[ModelA]
case tpe =>
Left(DecodingFailure("Unknown value " ++ tpe ++ " (valid: ModelA)", discriminatorCursor.history))
})
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.