20

Is there any way to automatically parse a case object from a string, in Scala? Using some built in / automatically generated Scala function?

For example, I have these case objects: (please note that there's a sealed parent class)

abstract sealed class FlagReason

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

and I'm wondering if there's some automatically generated function that works like:

FlagReason.fromString(value: String): FlagReason

where FlagReason("Spam") would return the Spam case object.

If there were, then I need not write my own -- which I've done:

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

Background: I'm converting my case objects to strings that I use as radio button values in a html form. I'm converting the selected value back to a case object, when I handle the submitted form.

Related info: This is actually possible with Java enums, see e.g. this StackOverflow question: Lookup enum by string value

((I don't think I'm looking for Scala's Parser Combinators. I suppose that were I to use them I'd still need to define the parsing rules myself, rather than having built in "automatic" string to case object conversion))

2
  • Note, that your link shows C# enums. Btw, can you provide a scenario, where you actually need such a feature? Commented Sep 23, 2011 at 14:05
  • @agilesteel: I've fixed the link now, thanks. I also added some info on why I do that kind of conversion. Commented Sep 23, 2011 at 18:40

2 Answers 2

33

No, no such method is automatically generated. You will have to write your own fromString method. Note that you can write it more compactly as follows:

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

Alternatively you may consider using scala.Enumeration which does provide this facility.

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

Then you can obtain the particular enum value with FlagReason withName "<name>", or safely as an Option with Try(FlagReason withName "<name>").toOption.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, something like extends Enumeration was kind of what I was hoping for :-)
4

As missingfaktor points out, FlagReason withName "<name>" should do what you need. But if <name> is not a valid name, it will throw an exception. So, a slightly safer way to handle this when you are not sure if the name is valid is to use 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.