6

I am trying to generate encoders and decoders for two case classes:

object EventBusCases {
  case class ValuationRequest(function: RequestValue = ALL_DAY_VALS, interval: RequestValue = IntraDayIntervals.MIN_5)
  implicit val requestDecoder: Decoder[ValuationRequest] = deriveDecoder[ValuationRequest]
  implicit val requestEncoder: Encoder[ValuationRequest] = deriveEncoder[ValuationRequest]

  case class ValuationResponse(values: List[Valuation], function: RequestValue)
  implicit val responseDecoder: Decoder[ValuationResponse] = deriveDecoder[ValuationResponse]
  implicit val responseEncoder: Encoder[ValuationResponse] = deriveEncoder[ValuationResponse]
}

I keep getting errors like this one, but for both cases: could not find Lazy implicit value of type io.circe.generic.encoding.DerivedAsObjectEncoder[eventbus.eventBusCases.ValuationResponse]

I decided to also try and derive encoders and decoders for the custom classes inside these ones, such as "Valuation", but I just get the same error on those ones.

I am using Circe 0.12.3 and Scala 2.12.8 and these are my Circe related Scala dependencies:

  "com.beachape" %% "enumeratum" % "1.5.14",
  "com.beachape" %% "enumeratum-circe" % "1.5.22",
  "io.circe" %% "circe-core" % "0.12.3",
  "io.circe" %% "circe-generic" % "0.12.3",
  "io.circe" %% "circe-parser" % "0.12.3"
LeYAUable
  • 1,613
  • 2
  • 15
  • 30
  • 2
    Just a guess - make sure that decoders/encoders for custom classes like `Valuation` are in implicit scope `deriveDecoder[ValuationResponse]` and `deriveEncoder[ValuationResponse]`. – Ivan Kurchenko Feb 03 '20 at 16:36
  • 1
    Yes they are basically the same as these ones. Inside an object with the case class and as "implicit val" – LeYAUable Feb 03 '20 at 16:42
  • 2
    Are they inside same `EventBusCases` object or different one? if different make sure, those implicits imported . Also a good practice to declare such type classes implicit instances inside companion objects, so they will be present in implicit scope. – Ivan Kurchenko Feb 03 '20 at 16:46
  • Valuation is a trait that is extended by 2 case classes and either one of them can come inside one ValuationResponse, could that be an issue? The list will have objects of one of thoses types, not the two types at the same type. – LeYAUable Feb 03 '20 at 17:54
  • yes, this is probably the issues - despite the fact that circe you have declared derived codecs for two sub-classes of `Valuation`, it does it mean that there is auto-derived codec for `Valuation` type itself, you need declare or implement it. Please see for more details: https://circe.github.io/circe/codecs/adt.html - it seems like describing your case. – Ivan Kurchenko Feb 03 '20 at 18:23
  • 1
    @IvanKurchenko I have posted an answer with the way I got it solved. In case you want to check. – LeYAUable Feb 10 '20 at 18:06

1 Answers1

1

So, the way I found to make this work was to implement Encoders and Decoders to both ValuationRequest and ValuationResponse, as well as to all custom types contained in them.

For ValuationRequest and ValuationResponse, I basically added this bit to the same file containing both case classes:

object derivation {
  implicit val encodeResponse: Encoder[ValuationResponse] = Encoder.instance {
    case response @ ValuationResponse(_,_) => response.asJson
  }
  implicit val decodeResponse: Decoder[ValuationResponse] =
    List[Decoder[ValuationResponse]](
      Decoder[ValuationResponse].widen
    ).reduceLeft(_ or _)

  implicit val encodeRequest: Encoder[ValuationRequest] = Encoder.instance {
    case response @ ValuationRequest(_,_) => response.asJson
  }
  implicit val decodeRequest: Decoder[ValuationRequest] =
    List[Decoder[ValuationRequest]](
      Decoder[ValuationRequest].widen
    ).reduceLeft(_ or _)
}
LeYAUable
  • 1,613
  • 2
  • 15
  • 30