2

I have a trait used to inject json decoder as dependency to components of my project:

trait JsonDecoder {
  def apply[T](s: String): Option[T]
}

When I try to implement it with Circe:

import io.circe.generic.auto._
import io.circe.parser.decode

case class CirceJsonDecoder() extends JsonDecoder {
  def apply[T](s: String): Option[T] = {
    decode[T](s).fold(_ => None, s => Some(s)) 
  }
}

and run:

case class C()

def test(d: JsonDecoder) = d[C]("{}")

test(CirceJsonDecoder())

it does not compile with error:

could not find implicit value for parameter decoder: io.circe.Decoder[T]

I tried to add ClassTag, TypeTag or WeakTypeTag context bounds for T but it still can not find implicit value for Decoder.

I can not add Decoder context bound or implicit parameter to JsonDecoder.apply because components what use it should not know about implementation details.

How should I provide implicit io.circe.Decoder? May be there is some way to get it from TypeTag?

mixel
  • 25,177
  • 13
  • 126
  • 165
  • 1
    From what I understand how you tried to fix it (adding reflection via `ClassTag`/`TypeTag`), you assume circe uses reflection to derive the json codecs. That's not the case. Instead, circe derives the codecs at compiletime, so it needs more information than just `T` about a type. You could try `shapeless.LabelledGeneric` or `shapless.Generic` context bound. – Reactormonk Dec 09 '16 at 15:38

1 Answers1

4

I don't think you can without affecting your apply method signature in any way involving circe. If you could, it'd mean circe.auto_ is capable of bringing an implicit decoder in scope for any type T, which is not true.

AFAIK, there's no better type annotation than adding an implicit Decoder to your function to signal circe that it actually knows how to handle this type (if you prefer, you can use the T: Decoder version, but it's the same in the end).

mixel
  • 25,177
  • 13
  • 126
  • 165
C4stor
  • 8,355
  • 6
  • 29
  • 47
  • Thanks! I upvoted your answer but I found the same question asked before and marked this as duplicate. I'll post my final solution there. I uses the type class approach as you and the guy from that question suggested. – mixel Dec 10 '16 at 11:22
  • See http://stackoverflow.com/a/41102192/746347. – mixel Dec 12 '16 at 13:43