Circe - 解码/编码 json 时在案例类中使用默认字段

Posted

技术标签:

【中文标题】Circe - 解码/编码 json 时在案例类中使用默认字段【英文标题】:Circe - Use default fields in case class when decoding/encoding json 【发布时间】:2018-05-03 11:11:00 【问题描述】:

假设我有这个案例类:

case class Foo(bar: String, baz: Boolean = false)

在使用akka-http-json对API请求/响应进行解码/编码时使用

在类似于this的示例中:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives
import akka.stream. ActorMaterializer, Materializer 
import scala.io.StdIn

object ExampleApp 

  private final case class Foo(bar: String, baz: Boolean = false)

  def main(args: Array[String]): Unit = 
    implicit val system = ActorSystem()
    implicit val mat    = ActorMaterializer()

    Http().bindAndHandle(route, "127.0.0.1", 8000)

    StdIn.readLine("Hit ENTER to exit")
    system.terminate()
  

  private def route(implicit mat: Materializer) = 
    import Directives._
    import FailFastCirceSupport._
    import io.circe.generic.auto._

    pathSingleSlash 
      post 
        entity(as[Foo])  foo =>
          complete 
            foo
          
        
      
    
  

只要 json 消息包含 baz 字段,它就可以正常工作。但是,我希望能够发送 json 消息bar: "something",并让结果使用Foo 的默认值bazcirceakka-http-json 中是否有任何配置可以完成这项工作?

另外,在再次编码为 json 时忽略 baz 字段会很好,但这并不重要。

编辑

我知道我可以这样做:

implicit val fooEncoder: Encoder[Foo] = new Encoder[Foo] 
    final def apply(a: Foo): Json = Json.obj(
      ("id", Json.fromString(a.bar))
    )
  

implicit val fooDecoder: Decoder[Foo] = new Decoder[Decoder] 
  final def apply(c: HCursor): Decoder.Result[Decoder] =
    for 
      bar <- c.downField("bar").as[String]
     yield 
      Foo(bar)
    

但希望有一个更易于维护的解决方案,解决不需要 json 消息中的默认字段的一般情况。

【问题讨论】:

使用Option[Boolean] 是一种有效的解决方法吗?并在不需要时将其设置为None @YuvalItzchakov 这是一个很好的建议,但在这种情况下,我们也将 case 类与quill 一起使用。由于我们数据库中的默认字段应为NOT NULL,因此最好将其保留为案例类中的非选项。 @simen-andresen 您应该考虑接受以下解决方案 【参考方案1】:

您可以使用 circe-generic-extras 包来执行此操作。这是您必须在构建中添加的单独依赖项。对于 sbt,就是:

libraryDependencies += "io.circe" %% "circe-generic-extras" % "0.8.0"

然后,在你的路由函数中,替换

import io.circe.generic.extras.Configuration
import io.circe.generic.auto._

与:

import io.circe.generic.extras.auto._
implicit val customConfig: Configuration = Configuration.default.withDefaults

此生成的编码器将始终包含默认字段。

有关更多信息,请参阅 circe 发行说明:https://github.com/circe/circe/releases/tag/v0.6.0-RC1

【讨论】:

以上是关于Circe - 解码/编码 json 时在案例类中使用默认字段的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

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

使用 circe 将 Scala None 编码为 JSON 值