如何在circe中编码/解码json的时间戳?

Posted

技术标签:

【中文标题】如何在circe中编码/解码json的时间戳?【英文标题】:How to encode/decode Timestamp for json in circe? 【发布时间】:2017-05-16 19:29:01 【问题描述】:

虽然在 slick 中使用 circe 来获取 json 中的数据,但我可以获取实体中没有 date(Timestamp/DateTime) 字段的数据。但是当我在 Entities 中使用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 Entities 并使用 CIRCE 进行 json 编码。

基表:

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: createdAt 生成编码器错误

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

用户表(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】:

您应该对您的代码使用自定义编码器和解码器,例如:

  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)
  

将此 val 放入任何需要编码/解码时间戳的代码中。例如,您可以将它放在一个对象中,并在需要的地方导入该对象。

【讨论】:

我尝试将 n 表添加为对象 UserTables class UserTable(tag : Tag) extends BaseTable[UserEntity](tag, "users") def updated_at = column[Option[String]](" updated_at") def * = (..., updated_at) (...) 隐式 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 ) 但是像以前一样得到编码器错误 你必须把 val 放在编码/解码实际完成的范围内(所以,可能在 http 相关代码附近的某个地方?),而不是在 sql 类中! 解码时,如何使用 DateTimeFormat 即 Y-m-d H:i:s 来解码而不是 decodeLong 您可以使用 decodeString.map(s => function(s)) 其中函数应该是一个函数来转换您在 Timestamp 中拥有的字符串(我想在过程中使用 DateTimeFormat)。 干杯! decodeString.map(s => new Timestamp(timestampFormatter.parse(s).getTime)).apply(c) 工作

以上是关于如何在circe中编码/解码json的时间戳?的主要内容,如果未能解决你的问题,请参考以下文章

带有案例类的抽象类的scala circe编码器/解码器

使用 circe 在 Scala 中 JSON 将嵌套字段解码为 Map[String, String]

使用 circe 解码 JSON 对象时捕获未使用的字段

用于编码/解码 arity 0 的密封特征实例的 Circe 实例?

Circe Scala - 编码和解码 Map[] 和案例类

尝试为ADT编写Circe编码器或解码器时遇到错误