以下是袖口,但它应该工作。请注意,我假设你只是想在当值是空分隔两侧空字符串,而我没有验证该月值是1到12之间
import argonaut._, Argonaut._
import scalaz._, Scalaz._
case class DateValue(year: Option[Int] = None, month: Option[Int] = None)
object YearMonth {
def unapplySeq(s: String) =
"""((?:\d\d\d\d)?)/((?:\d?\d)?)""".r.unapplySeq(s).map {
case List("", "") => List(None, None)
case List(y, "") => List(Some(y.toInt), None)
case List("", m) => List(None, Some(m.toInt))
case List(y, m) => List(Some(y.toInt), Some(m.toInt))
}
}
implicit val DateValueCodecJson: CodecJson[DateValue] = CodecJson(
{ case DateValue(year, month) => jString(~year + "/" + ~month) },
c => c.as[String].flatMap {
case YearMonth(y, m) => DecodeResult.ok(DateValue(y, m))
case _ => DecodeResult.fail("Not a valid date value!", c.history)
}
)
然后:
val there = Parse.decodeValidation[DateValue](""""2013/12"""")
val back = there.map(DateValueCodecJson.encode)
这给了我们:
scala> println(there)
Success(DateValue(Some(2013),Some(12)))
scala> println(back)
Success("2013/12")
正如预期的那样。
诀窍是提供您自己的编码和解码功能CodecJson.apply
。编码函数非常简单 - 它只需要一些编码类型并返回Json
值。解码方法稍微复杂一点,因为它需要一个HCursor
并返回一个DecodeResult
,但这些也很容易处理。
正是我在找的东西。谢谢你,特拉维斯。 '〜'操作符对我来说也是一个很棒的发现。 – Tvaroh