我有基于JSON和Play Framework的scala REST服务。 JSON的某些字段是可选的(例如middleName)。我可以标记选项,例如
middleName: Option[String]
甚至不希望它出现在JSON中。但我希望将来避免可能的应用程序错误并简化生活。如果用户不想提供此信息并且整个应用程序中没有选项字段(JSON / DB开销很小),我想将其标记为可预期但空。
在整个应用程序中避免选项字段是否是个好主意?如果String字段为空,则它包含一个空字符串,但JSON / DB中存在manadatory。如果Int字段为空,则它包含0等
提前致谢
答案 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
,我假设您主要使用它来以个人方式对用户进行处理,并且您只是连接title
,firstName
,middleName
和lastName
。因此,无论用户是否指定了值,您都会将值视为完全相同。所以我认为使用空字符串而不是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("")