【问题标题】:Scala case class whose fields can be mandatory and optional at different instancesScala 案例类,其字段在不同实例中可以是强制性的和可选的
【发布时间】:2019-02-09 11:34:03
【问题描述】:

我在akka http 中创建了两个rest 端点,它们将字符串作为输入,使用Json4s 对其进行解析,然后对其进行处理。我的案例类就像 -

final case class A(id: String, name: String, address: String)

第一个端点仅接收 id 而另一个接收所有三个字段,我想对两者使用相同的案例类 A。所以我使用了名称和地址字段的默认值,例如 -

final case class A(id: Stirng, name: String = "", address: String = "")

这对我很有用。但是现在,如果我不在第二个端点发送地址或名称(或两者)字段,它不会抛出异常说明未找到名称(或地址)。

所以,我的问题是我是否可以创建一个端点,其中 id 是强制性的,而其他字段无关紧要,另一个端点是每个字段都是强制性的,使用相同的案例类? 将字符串解析为案例类的代码是 -

parse(jsonStr).extract[A]

我希望你明白我的意思。

有什么建议吗?

【问题讨论】:

  • 你不能用两个不同的请求创建一个端点。您将不得不进行验证。使用 Option[String] 作为名称和地址。当您发送姓名和地址时,请执行 name.get 和 address.get
  • 使用 play-json 你可以使用Json.using[Json.WithDefaultValues] - 也许json4s 有类似的概念
  • 使用 jsoniter-scala 代替 - 它具有对案例类字段的内置处理,默认值是可选的,并且还与 akka-http 集成:github.com/hseeberger/akka-http-json/pull/205

标签: scala case-class json4s


【解决方案1】:

有两种方法可以实现你想做的事情。

选项 + 验证

姓名和地址是可选的,所以你需要处理它们。

case class A(id: String, name: Option[String], address: Option[String])

val json = """{ "id":"1" }"""

// 1st endpoint
val r = parse(json).extract[A]
r.name.getOrElse("foo")
r.address.getOrElse("bar")

// 2nd endpoint
val r2 = parse(json).extract[A]
r2.name.getOrElse(/* boom! */)

默认 JObject + 合并

或者您可以使用替代的 JObject 为您的输入提供默认值。

case class A(id: String, name: String, address: String)

val json = """{ "id":"1"  }"""

val defaultValues = JObject(("name", JString("foo")), ("address", JString("bar")))

// 1st endpoint
val r = defaultValues.merge(parse(json)).extract[A]

// 2nd endpoint
val r2 = parse(json).extract[A] // boom! again

【讨论】:

    【解决方案2】:

    您的案例类没有正式定义您对输入的期望。它并不代表模棱两可。您可以使用可选并添加检查。但这只是违背了提取器的目的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-27
      • 2017-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 2020-11-14
      • 1970-01-01
      相关资源
      最近更新 更多