Basically I have a slew of optionals coming in as JSON, because as we all know even the most strict schema has edge case missing values. When trying to turn Option[A]
to string with the standard interpolator it looks like:
None,Some("us"),None,Some(14)
So here's a better way that uses an interpolator for Option[A]
which yields code that looks like:
val city = None
val country = Some("us")
val language = None
val decibels = Some(14)
o"$city,$country,$language,$decibels"
produces:
,us,,14
And here's the magic, mostly stolen from the Scala StringContext
source code:
implicit class OptionStringInterpolator(val sc: StringContext) extends AnyVal {
import sc.parts
def o(args: Any*) = optionInterpolator(StringContext.treatEscapes, args)
private def optionInterpolator(process: String => String, args: Seq[Any]): String = {
checkLengths(args)
val pi = parts.iterator
val ai = args.iterator
val builder = new StringBuilder(process(pi.next()))
while (ai.hasNext) {
val resolved = ai.next() match {
case Some(s) => s
case None => ""
case o => o
}
builder append resolved
builder append process(pi.next())
}
builder.toString()
}
def checkLengths(args: Seq[Any]): Unit =
if (parts.length != args.length + 1)
throw new IllegalArgumentException("wrong number of arguments ("+ args.length
+") for interpolated string with "+ parts.length +" parts")
}