如何通过 Doobie 将案例对象插入为 JSONB 格式?
How I can insert case object as JSONB format via Doobie?
我使用 scala 2.13 和 doobie 0.12.1
例如,
我有案例 class
case class UserInfo(name: String, age: Int, hobbies: Vector[String])
我想在列信息中插入用户信息作为 jsonb
sql"""
INSERT INTO users(
id,
info
created_at,
) values (
${id},
${userInfo},
${createdAt},
)
""".update.run.transact(t)
在我的 DAO 中我有隐含的 val
implicit val JsonbMeta: Meta[Json] = Meta
.Advanced.other[PGobject]("jsonb")
.timap[Json](jsonStr => parser.parse(jsonStr.getValue).leftMap[Json](err => throw err).merge)(json => {
val o = new PGobject
o.setType("jsonb")
o.setValue(json.noSpaces)
o
})
但是我有编译异常
found : ***.****.UserInfo
[error] required: doobie.syntax.SqlInterpolator.SingleFragment[_]; incompatible interpolation method sql
[error] sql"""
[error] ^
您已经为类型 Json
定义了 Meta
,但看起来您在插入的字符串中使用了 UserInfo
的实例。尝试将对象转换为 Json
并将其传递给 sql
:
// This assumes you're using Circe as your JSON library
import io.circe._, io.circe.generic.semiauto._, io.circe.syntax._
implicit val userInfoEncoder: Encoder[UserInfo] = deriveEncoder[UserInfo]
val userInfo: UserInfo = UserInfo("John", 50, Vector("Scala"))
val userInfoJson: Json = userInfo.asJson // requires Encoder[UserInfo]
// and then, assuming that an implicit Meta[Json] is in scope
sql"""INSERT INTO users(
id,
info
created_at,
) values (
${id},
${userInfoJson}, -- instance of Json here
${createdAt},
)"""
doobie-postgres-circe module提供pgEncoderPut
和pgDecoderGet
。有了这些,以及范围内的隐式循环 Encoder
和 Decoder
,您可以创建一个 Meta[UserInfo]
。那么您的示例插入应该可以工作。
用法示例:
// Given encoder & decoder (or you could import io.circe.generic.auto._)
implicit encoder: io.circe.Encoder[UserInfo] = ???
implicit decoder: io.circe.Decoder[UserInfo] = ???
import doobie.postgres.circe.jsonb.implicits.{pgDecoderGet, pgEncoderPut}
implicit val meta: Meta[UserInfo] = new Meta(pgDecoderGet, pgEncoderPut)
我使用 scala 2.13 和 doobie 0.12.1
例如, 我有案例 class
case class UserInfo(name: String, age: Int, hobbies: Vector[String])
我想在列信息中插入用户信息作为 jsonb
sql"""
INSERT INTO users(
id,
info
created_at,
) values (
${id},
${userInfo},
${createdAt},
)
""".update.run.transact(t)
在我的 DAO 中我有隐含的 val
implicit val JsonbMeta: Meta[Json] = Meta
.Advanced.other[PGobject]("jsonb")
.timap[Json](jsonStr => parser.parse(jsonStr.getValue).leftMap[Json](err => throw err).merge)(json => {
val o = new PGobject
o.setType("jsonb")
o.setValue(json.noSpaces)
o
})
但是我有编译异常
found : ***.****.UserInfo
[error] required: doobie.syntax.SqlInterpolator.SingleFragment[_]; incompatible interpolation method sql
[error] sql"""
[error] ^
您已经为类型 Json
定义了 Meta
,但看起来您在插入的字符串中使用了 UserInfo
的实例。尝试将对象转换为 Json
并将其传递给 sql
:
// This assumes you're using Circe as your JSON library
import io.circe._, io.circe.generic.semiauto._, io.circe.syntax._
implicit val userInfoEncoder: Encoder[UserInfo] = deriveEncoder[UserInfo]
val userInfo: UserInfo = UserInfo("John", 50, Vector("Scala"))
val userInfoJson: Json = userInfo.asJson // requires Encoder[UserInfo]
// and then, assuming that an implicit Meta[Json] is in scope
sql"""INSERT INTO users(
id,
info
created_at,
) values (
${id},
${userInfoJson}, -- instance of Json here
${createdAt},
)"""
doobie-postgres-circe module提供pgEncoderPut
和pgDecoderGet
。有了这些,以及范围内的隐式循环 Encoder
和 Decoder
,您可以创建一个 Meta[UserInfo]
。那么您的示例插入应该可以工作。
用法示例:
// Given encoder & decoder (or you could import io.circe.generic.auto._)
implicit encoder: io.circe.Encoder[UserInfo] = ???
implicit decoder: io.circe.Decoder[UserInfo] = ???
import doobie.postgres.circe.jsonb.implicits.{pgDecoderGet, pgEncoderPut}
implicit val meta: Meta[UserInfo] = new Meta(pgDecoderGet, pgEncoderPut)