避免使用Option字段。始终为String填充字符串,为Int可选字段填充0

时间:2015-01-08 07:06:31

标签: json scala rest

我有基于JSON和Play Framework的scala REST服务。 JSON的某些字段是可选的(例如middleName)。我可以标记选项,例如

 middleName: Option[String]

甚至不希望它出现在JSON中。但我希望将来避免可能的应用程序错误并简化生活。如果用户不想提供此信息并且整个应用程序中没有选项字段(JSON / DB开销很小),我想将其标记为可预期但空。

在整个应用程序中避免选项字段是否是个好主意?如果String字段为空,则它包含一个空字符串,但JSON / DB中存在manadatory。如果Int字段为空,则它包含0等

提前致谢

4 个答案:

答案 0 :(得分:2)

我认为你会因为失去类型安全而后悔避免Option。如果你去传递可能为空的对象引用,那么触摸它们的每个人都必须记住来检查null,因为没有任何东西会强制它们这样做。不记得是NullPointerException等待发生。使用Option强制代码来处理没有价值可行的可能性;忘记这样做会导致编译错误:

case class Foo(name: Option[String])
...
if (foo1.name startsWith "/")  // ERROR: no startsWith on Option

我偶尔会在一个非常本地化的代码中使用空值,我认为性能很重要,或者我有很多很多对象,并且不希望拥有所有这些Some和{{ 1}}对象占用内存,但我绝不会在公共API中泄漏null。使用零点是一个复杂的优化,只有在通过利益证明避免灾难所需的额外警惕时才应使用。这种情况很少见。

我不完全确定我理解您对JSON的需求,但听起来您可能希望{J}文档中的None字段不会消失。在Spray-json中,有一个Option特征专门针对此。您只需将其混合到您的协议类型中,它就会影响其中定义的所有NullOptions(您可以使用其他协议类型,而不是"如果您愿意,可以混合使用),例如

JsonFormat

如果没有trait FooJsonProtocol extends DefaultJsonProtocol with NullOptions { // your jsonFormats } ,则会完全省略值NullOptions的{​​{1}}成员;有了它,它们会显示Option个值。我认为如果您显示带有空值的可选字段而不是让它们消失,用户会更清楚,但为了提高传输效率,您可能希望省略它们。至少使用Spray-json,你可以选择。

我不知道其他JSON软件包是否有类似的选项,但如果由于某种原因你不想使用Spray-json(顺便说一句,这可能会帮助你找到它) ,现在非常快。)

答案 1 :(得分:1)

我认为这取决于您的业务逻辑以及您希望如何使用这些值。

对于middleName,我假设您主要使用它来以个人方式对用户进行处理,并且您只是连接titlefirstNamemiddleNamelastName。因此,无论用户是否指定了值,您都会将值视为完全相同。所以我认为使用空字符串而不是None可能更好。

对于0""就业务逻辑而言是有效值的值,我会使用Option[String],同样在您有不同行为的情况下取决于是否指定了值。

x match {
  case 0 => foo
  case _ => bar(_) 
}

的描述性低于

x match {
  case Some(i) => bar(i)
  case None => foo
}

答案 2 :(得分:1)

这是一个坏主意,因为通常你想要处理不同的东西。如果你传递的值是""或者0左右,这很容易与实际值混淆;你最终可能会发送一封电子邮件,开始"亲爱的先生,"或者祝他们35岁生日快乐,因为时间戳0出现在1970年1月1日。如果你在代码和类型系统中对值None进行区分,这会迫使你思考一个值是否真的设置以及如果不是你想做什么。

不要盲目地推动Option到处都是。如果没有提供值的错误,您应该立即检查并尽快抛出错误,而不是等到应用程序的更晚版本,因为它将更难调试{{1来自。

答案 3 :(得分:1)

它不会让您的生活变得更轻松"。如果有的话,它会使它变得更难,而不是避免应用程序错误将使它们更有可能。您的应用代码必须使用if(middleName != "") { doSomething(middleName); }if(age == 0) "Unknown age" else age.toString等支票进行侵扰,您必须依赖程序员记住处理这些"有点可选"田野以特殊的方式。

所有这一切你都可以获得免费"使用带有middleName.foreach(doSomething)age.map(_.toString).getOrElse("")

的Option的monadic属性