2017-01-27 92 views
4

我想使用http4s,circe和http4s-circe。Circe编码器和解码器与Http4

下面我试图使用circe的自动派生功能。

import org.http4s.client.blaze.SimpleHttp1Client 
import org.http4s.Status.ResponseClass.Successful 
import io.circe.syntax._ 
import org.http4s._ 
import org.http4s.headers._ 
import org.http4s.circe._ 
import scalaz.concurrent.Task 
import io.circe._ 

final case class Login(username: String, password: String) 
final case class Token(token: String) 

object JsonHelpers { 
    import io.circe.generic.auto._ 
    implicit val loginEntityEncoder : EntityEncoder[Login] = jsonEncoderOf[Login] 
    implicit val loginEntityDecoder : EntityDecoder[Login] = jsonOf[Login] 
    implicit val tokenEntityEncoder: EntityEncoder[Token] = jsonEncoderOf[Token] 
    implicit val tokenEntityDecoder : EntityDecoder[Token] = jsonOf[Token] 
} 

object Http4sTest2 extends App { 
    import JsonHelpers._ 
    val url = "http://" 
    val uri = Uri.fromString(url).valueOr(throw _) 
    val list = List[Header](`Content-Type`(MediaType.`application/json`), `Accept`(MediaType.`application/json`)) 
    val request = Request(uri = uri, method = Method.POST) 
     .withBody(Login("foo", "bar").asJson) 
     .map{r => r.replaceAllHeaders(list :_*)}.run 
    val client = SimpleHttp1Client() 
    val result = client.fetch[Option[Token]](request){ 
     case Successful(response) => response.as[Token].map(Some(_)) 
     case _ => Task(Option.empty[Token]) 
    }.run 
    println(result) 
} 

我得到这两种编译器错误

Error:scalac: missing or invalid dependency detected while loading class file 'GenericInstances.class'. 
Could not access type Secondary in object io.circe.Encoder, 
because it (or its dependencies) are missing. Check your build definition for 
missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.) 
A full rebuild may help if 'GenericInstances.class' was compiled against an incompatible version of io.circe.Encoder. 


Error:(25, 74) could not find implicit value for parameter encoder: io.circe.Encoder[Login] 
    implicit val loginEntityEncoder : EntityEncoder[Login] = jsonEncoderOf[Login] 
+2

的代码,我并不十分熟悉的设计决策中http4s,但我认为它只是为'io.circe.Json'提供'EntityEncoder'实例,而不是'io.circe.Encoder'实例。在你的情况下,你可以通过使用circe的泛型派生并在'withBody'的'Login'中调用'asJson'来跳过所有八个明确定义的实例。 –

回答

4

我能解决这个问题的多个实例。我在sbt circe依赖项上搜索了google,并复制粘贴了第一个搜索结果。那是0.1左右,这就是为什么事情不适合我。

我改变了我的依赖关系

libraryDependencies ++= Seq(
    "org.http4s" %% "http4s-core" % http4sVersion, 
    "org.http4s" %% "http4s-dsl" % http4sVersion, 
    "org.http4s" %% "http4s-blaze-client" % http4sVersion, 
    "org.http4s" %% "http4s-circe" % http4sVersion, 
    "io.circe" %% "circe-core" % "0.7.0", 
    "io.circe" %% "circe-generic" % "0.7.0" 
) 

现在自动派生正常工作,我能够编译如下

import org.http4s.client.blaze.SimpleHttp1Client 
import org.http4s._ 
import org.http4s.headers._ 
import org.http4s.circe._ 

import scalaz.concurrent.Task 
import io.circe.syntax._ 
import io.circe.generic.auto._ 
import org.http4s.Status.ResponseClass.Successful 

case class Login(username: String, password: String) 
case class Token(token: String) 

object JsonHelpers { 
    implicit val loginEntityEncoder : EntityEncoder[Login] = jsonEncoderOf[Login] 
    implicit val loginEntityDecoder : EntityDecoder[Login] = jsonOf[Login] 
    implicit val tokenEntityEncoder: EntityEncoder[Token] = jsonEncoderOf[Token] 
    implicit val tokenEntityDecoder : EntityDecoder[Token] = jsonOf[Token] 
} 

object Http4sTest2 extends App { 
    import JsonHelpers._ 
    val url = "http://" 
    val uri = Uri.fromString(url).valueOr(throw _) 
    val list = List[Header](`Content-Type`(MediaType.`application/json`), `Accept`(MediaType.`application/json`)) 
    val request = Request(uri = uri, method = Method.POST) 
     .withBody(Login("foo", "bar").asJson) 
     .map{r => r.replaceAllHeaders(list :_*)}.run 
    val client = SimpleHttp1Client() 
    val result = client.fetch[Option[Token]](request){ 
     case Successful(response) => response.as[Token].map(Some(_)) 
     case _ => Task(Option.empty[Token]) 
    }.run 
    println(result) 
}