Generic json decoder trait with Circe implementati

2019-07-22 19:26发布

问题:

This question already has an answer here:

  • Scala Circe with generics 2 answers

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?

回答1:

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).



标签: scala circe