2017-06-16 2 views
0

Je construis un très simplement un service, qui devrait retourner un arbre comme la structure définie par une classe de cas récursif:codage structure de données récursive en JSON avec Circé lors de l'exécution sur http4s

case class Node(id: Int, name: String, children: Seq[Node] = Seq()) 

Mais pour une raison que je garde obtenir une erreur de compilation suivante:

Error:(24, 70) could not find implicit value for parameter encoder: io.circe.Encoder[Seq[com.ansarada.ds.docviewer.server.Main.Node]]
implicit val nodesEncoder: EntityEncoder[Seq[Node]] = jsonEncoderOf[Seq[Node]]

Error:(24, 70) not enough arguments for method jsonEncoderOf: (implicit encoder: io.circe.Encoder[Seq[com.ansarada.ds.docviewer.server.Main.Node]])org.http4s.EntityEncoder[Seq[com.ansarada.ds.docviewer.server.Main.Node]]. Unspecified value parameter encoder. implicit val nodesEncoder: EntityEncoder[Seq[Node]] = jsonEncoderOf[Seq[Node]]

Le code est compilé, une fois que je supprimer une définition de l'élément enfants et tourner un nœud dans un objet plat:

case class Node(id: Int, name: String) 

Quelqu'un peut-il m'aider à définir l'encodeur Json correct pour un cas avec des enfants imbriqués?

code complet:

import org.http4s.circe._ 
import org.http4s.dsl._ 
import org.http4s.server.blaze.BlazeBuilder 
import org.http4s.server.{Server, ServerApp} 
import org.http4s.{EntityEncoder, HttpService} 

import scalaz.concurrent.Task 

object Main extends ServerApp { 
    import io.circe.generic.auto._ 
    import io.circe.syntax._ 

    case class Node(id: Int, name: String, children: Seq[Node] = Seq()) 

    def getNodes: Seq[Node] = Seq(
    Node(0, "#One"), 
    Node(1, "#Two"), 
    Node(2, "#Three") 
) 

    implicit val nodeEncoder: EntityEncoder[Node] = jsonEncoderOf[Node] 
    implicit val nodesEncoder: EntityEncoder[Seq[Node]] = jsonEncoderOf[Seq[Node]] 

    override def server(args: List[String]): Task[Server] = { 
    val nodesService = HttpService { 
     case _ @ GET -> Root/"nodes" => 
     Ok(getNodes.asJson) 
    } 

    BlazeBuilder 
     .bindHttp(8080, "localhost") 
     .mountService(nodesService, "/api") 
     .start 
    } 
} 

Répondre

0

Ok. J'ai réussi à utiliser les annotations de circe json - @JsonCodec. étape par étape pour résoudre un problème décrit ci-dessus:

  1. Pré-requis - import Circé lib:

    "io.circe" %% "circe-core" % "0.8.0", 
    "io.circe" %% "circe-generic" % "0.8.0", 
    "io.circe" %% "circe-literal" % "0.8.0", 
    "io.circe" %% "circe-parser" % "0.8.0", 
    
  2. plugins compilateur Turn automatique dans votre build.sbt:

    autoCompilerPlugins := true 
    
  3. Ajouter un plugin compilateur scalamacros paradise:

    lazy val root = Project("root", file(".")) 
        .settings(
         addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.patch) 
    ) 
    
  4. cours Annoter de cas avec @JsonCodec:

    @JsonCodec case class Node(id: Int, children: Seq[Node] = Seq()) 
    
  5. réponse Cast JSON:

    Ok(getNodes.asJson) 
    

extrait de code complet:

import org.http4s.circe._ 
import org.http4s.dsl._ 
import org.http4s.server.blaze.BlazeBuilder 
import org.http4s.server.{Server, ServerApp} 
import org.http4s.{EntityEncoder, HttpService} 

import scalaz.concurrent.Task 
object Main extends ServerApp { 
    import io.circe.generic.auto._ 
    import io.circe.syntax._ 

    @JsonCodec case class Node(id: Int, name: String, children: Seq[Node] = Seq()) 

    def getNodes: Seq[Node] = Seq(
    Node(0, "#One"), 
    Node(1, "#Two"), 
    Node(2, "#Three") 
) 

    override def server(args: List[String]): Task[Server] = { 
    val nodesService = HttpService { 
     case _ @ GET -> Root/"nodes" => 
     Ok(getNodes.asJson) 
    } 

    BlazeBuilder 
     .bindHttp(8080, "localhost") 
     .mountService(nodesService, "/api") 
     .start 
    } 
}