如何在circe中对JSON进行时间戳编码/解码?

17

在使用Slick中的circe从JSON中获取数据时,我可以获取没有日期(Timestamp/DateTime)字段的实体数据。但是,如果我在实体中使用Timestamp字段,则会出现错误:

[error] /var/www/html/scala-api/src/main/scala/oc/api/http/routes/TestApi.scala:40: could not find implicit value for parameter encoder: io.circe.Encoder[Seq[oc.api.models.UserEntity]]
[error]             auth => complete(userDao.getAll().map(_.asJson))

这是我为Slick实体使用CIRCE进行JSON编码所使用的代码。
BaseTable:
abstract class BaseTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def createdAt = column[Timestamp]("created_at")
  def updatedAt = column[Timestamp]("updated_at")
  def deletedAt = column[Timestamp]("deleted_at")
}

基础实体类:

trait BaseEntity {
  val id : Long
  def isValid : Boolean = true
}

UserEntity: 创建时间生成编码器错误

case class UserEntity(id: Long, email: String, password: String, createdAt: Timestamp) extends BaseEntity

UserEntity: 这个完美地运作了

case class UserEntity(id: Long, email: String, password: String) extends BaseEntity

UserTable(Slick):

object UserTables {

  class UserTable(tag : Tag) extends BaseTable[UserEntity](tag, "users") {
    def name = column[String]("name")
    def password = column[String]("password")
    def * = (id, name, password) <> (UserEntity.tupled, UserEntity.unapply)
  }

  implicit val accountsTableQ : TableQuery[UserTable] = TableQuery[UserTable]
}

我的代码有什么问题吗?非常感谢您的帮助。

1个回答

17

你应该在你的代码中使用自定义编码器和解码器,就像这样:

  implicit val TimestampFormat : Encoder[Timestamp] with Decoder[Timestamp] = new Encoder[Timestamp] with Decoder[Timestamp] {
    override def apply(a: Timestamp): Json = Encoder.encodeLong.apply(a.getTime)

    override def apply(c: HCursor): Result[Timestamp] = Decoder.decodeLong.map(s => new Timestamp(s)).apply(c)
  }

将此值放入需要编码/解码时间戳的任何代码中。例如,您可以将其放入对象中,并在需要时导入该对象。


我尝试将n个表添加为对象UserTables:object UserTables { class UserTable(tag : Tag) extends BaseTable[UserEntity](tag, "users") { def updated_at = column[Option[String]]("updated_at") def * = (..., updated_at) <> (...) } implicit val TimestampFormat : Encoder[Timestamp] with Decoder[Timestamp] = new Encoder[Timestamp] with Decoder[Timestamp] { override def apply(a: Timestamp): Json = Encoder.encodeLong.apply(a.getTime) override def apply(c: HCursor): Result[Timestamp] = Decoder.decodeLong.map(s => new Timestamp(s)).apply(c) } }但是出现了编码器错误。 - Sujit Baniya
你必须将val放在编码/解码实际完成的范围内(因此,可能是在与http相关的代码附近的某个地方?),而不是在sql类中! - C4stor
在解码时,我如何使用DateTimeFormat即Y-m-d H:i:s进行解码,而不是使用decodeLong? - Sujit Baniya
1
你可以使用 decodeString.map(s => function(s)),其中 function 应该是一个将你所拥有的字符串转换为时间戳的函数(在此过程中使用 DateTimeFormat)。 - C4stor
干杯! decodeString.map( s => new Timestamp(timestampFormatter.parse(s).getTime)).apply(c) 工作正常。 - Sujit Baniya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接