13

可以说我有这个案例类:

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

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

在与此类似的示例中:

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"}让结果使用. 是否有任何配置或可以使这项工作?Foobazcirceakka-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 消息中的默认字段的一般情况。

4

1 回答 1

20

您可以使用 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

于 2017-12-05T00:38:07.173 回答