无法找到或构造 Param[shapeless.::[String,shapeless.::[io.circe.Json,shapeless.HNil]]]

Could not find or construct Param[shapeless.::[String,shapeless.::[io.circe.Json,shapeless.HNil]]]

我正在开发一个用于练习的基本求职板应用程序,在尝试编译我的 Scala 代码时出现以下错误。

[warn] insecure HTTP request is deprecated 'http://repo.typesafe.com/typesafe/releases/'; switch to HTTPS or opt-in as ("Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/").withAllowInsecureProtocol(true)
[info] Compiling 8 Scala sources to /Users/ryanmcavoy/Code/job-board/target/scala-2.11/classes ...
[error] /Users/ryanmcavoy/Code/job-board/src/main/scala/io/github/jobboard/database/JobQueries.scala:26:5: Could not find or construct Param[shapeless.::[String,shapeless.::[io.github.jobboard.model.JobPostDetails,shapeless.HNil]]].
[error] Ensure that this type is an atomic type with an Meta instance in scope, or is an HList whose members
[error] have Meta instances in scope. You can usually diagnose this problem by trying to summon the Meta
[error] instance for each element in the REPL. See the FAQ in the Book of Doobie for more hints.
[error]     sql"""
[error]     ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed

好像是在抱怨下面的方法

  def insert(jobPost: JobPost): doobie.Update0 = {
    sql"""
         |INSERT INTO jobs (
         |  id,
         |  details
         |)
         |VALUES (
         |  ${jobPost.id},
         |  ${jobPost.details}
         |)
        """.stripMargin
      .update
  }

我已经查看了此处的文档:https://tpolecat.github.io/doobie-0.2.3/15-FAQ.html,但未能弄明白。

有关其他信息,我将包括以下内容:

case class JobPost(id: String, details: JobPostDetails)

case class JobPostDetails(title: String, description: String, salary: Double, employmentType: String, employer: String)
    def createTable: doobie.Update0 = {
      sql"""
           |CREATE TABLE IF NOT EXISTS jobs (
           |  id UUID PRIMARY KEY,
           |  details JSON NOT NULL
           |)
       """.stripMargin
        .update
    }

在你的情况下,Doobie 不知道如何将 JobPostDetails 序列化到你的 Postgres 数据库的 JSON 列中。

默认情况下,Doobie 不知道如何将大小写 class 更改为 JSON。可以说,在 scala 中用于序列化 JSON 的最流行的库是 circe。您必须在 build.sbt 中为 circe 和 circe-Postgres-doobie 集成添加额外的依赖项。

"org.tpolecat" %% "doobie-postgres" % "0.8.8"
"org.tpolecat" %% "doobie-postgres-circe" % "0.8.8"
"io.circe" %% "circe-core" % "0.13.0"

那么你应该在 JobPostDetails 的伴生对象中创建 EncoderDecoderPutGet 类型 classes 的实例:

import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import doobie.postgres.circe.json.implicits._
import doobie._
import io.circe.syntax._

case class JobPostDetails(title: String, description: String, salary: Double, employmentType: String, employer: String)

object JobPostDetails {

  //for decoding json into JobPostDetails
  implicit val circeDecoder: Decoder[JobPostDetails] =
    deriveDecoder[JobPostDetails]

  //for encoding JobPostDetails into json
  implicit val circeEncoder: Encoder[JobPostDetails] =
    deriveEncoder[JobPostDetails]

  //tells doobie to put JobPostDetails as json to details column
  implicit val put: Put[JobPostDetails] =
    Put[Json].contramap(_.asJson) 

  //tells doobie how to read JobPostDetails from json column
  implicit val get: Get[JobPostDetails] =
    Get[Json].temap(_.as[JobPostDetails].leftMap(_.show)) 
}

之后,您应该可以保存 JobPost