Generic json decoder trait with Circe implementati

2019-07-22 19:10发布

This question already has an answer here:

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?

标签: scala circe
1条回答
混吃等死
2楼-- · 2019-07-22 20:04

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

查看更多
登录 后发表回答