Построен в разборе строки в объект объекта Scala?

Есть ли способ автоматического анализа объекта case из строки, в Scala? Использование некоторой встроенной/автоматически созданной функции Scala?

Например, у меня есть такие объекты case: (обратите внимание, что существует закрытый родительский класс)

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") вернет объект case Spam.

Если бы это было, тогда мне не нужно писать самостоятельно - что я сделал:

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

Фон: я конвертирую объекты case в строки, которые я использую в качестве значений переключателей в форме html. Я конвертирую выбранное значение обратно в объект case, когда обрабатываю представленную форму.

Сопутствующая информация: это действительно возможно с перечислениями Java, см., например, этот вопрос StackOverflow: Перечислить нумерацию по строковому значению

((Я не думаю, что я ищу Scala Parser Combinators. Я полагаю, что если бы я использовал их, мне все равно нужно было бы определять правила разбора, а не создавать "автоматическую" строку к преобразованию объекта case))

Ответы

Ответ 1

Нет, такой метод не генерируется автоматически. Вам придется написать свой собственный метод 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.

Ответ 2

Как missingfaktor указывает, FlagReason withName "<name>" должен делать то, что вам нужно. Но если <name> не является допустимым именем, оно генерирует исключение. Итак, немного более безопасный способ справиться с этим, если вы не уверены, что имя действительно, это использовать Option[FlagReason]:

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

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

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