内置解析字符串到Scala案例对象?

时间:2011-09-23 13:52:12

标签: parsing scala

有没有办法在Scala中自动解析字符串中的case对象?使用一些内置/自动生成的Scala函数?

例如,我有这些案例对象:(请注意有一个密封的父类)

abstract sealed class FlagReason

case object Spam extends FlagReason
case object Illegal extends FlagReason
case object CopyrightViolation extends FlagReason
case object Other extends FlagReason

我想知道是否有一些自动生成的功能如下:

FlagReason.fromString(value: String): FlagReason

其中FlagReason("Spam")将返回Spam案例对象。

如果有,那我就不用自己编写了 - 我已经完成了:

object FlagReason {
  def fromString(value: String): FlagReason = value match {
    case "Spam" => Spam
    case "Illegal" => Illegal
    case "CopyrightViolation" => CopyrightViolation
    case "Other" => Other
  }
}

背景:我正在将我的case对象转换为我用作html格式的单选按钮值的字符串。当我处理提交的表单时,我正在将选定的值转换回案例对象。

相关信息:这实际上可以使用Java枚举,例如,这个StackOverflow问题:Lookup enum by string value

((我不认为我在寻找Scala的Parser Combinators。我想我要使用它们我仍然需要自己定义解析规则,而不是内置“自动”字符串到案例对象转换))

2 个答案:

答案 0 :(得分:28)

不,不会自动生成此类方法。您必须编写自己的fromString方法。请注意,您可以按如下方式更紧凑地编写它:

object FlagReason {
  def fromString(value: String): Option[FlagReason] = {
    Vector(Spam, Illegal, CopyRightViolation, Other).find(_.toString == value)
  }
}

或者,您可以考虑使用提供此功能的scala.Enumeration

object FlagReason extends Enumeration {
  val Spam, Illegal, CopyRightViolation, Other = Value
}

然后,您可以使用FlagReason withName "<name>"获取特定的枚举值,或使用Option安全地获取Try(FlagReason withName "<name>").toOption

答案 1 :(得分:3)

正如missingfaktor指出的那样,FlagReason withName "<name>"应该做你需要的。但是如果<name>不是有效名称,它将抛出异常。因此,当您不确定名称是否有效时,稍微更安全的方法是使用Option[FlagReason]

scala> def parse(name: String) = FlagReason.values.find(_.toString == name)
parse: (name: String)Option[FlagReason.Value]

scala> parse("Spam")
res0: Option[FlagReason.Value] = Some(Spam)

scala> parse("NonExisting")
res1: Option[FlagReason.Value] = None