2013-10-24 8 views
2

Модель:Аргонавт, пользовательские JSON отображение формата

case class DateValue(year: Option[Int] = None, month: Option[Int] = None) 

Аргонавт на основе декодера:

implicit val dateValueDecode = casecodec2(DateValue.apply, DateValue.unapply)("year", "month") 

Это позволяет анализировать такой формат:

{ 
    "year": "2013", 
    "month": "10" 
} 

Теперь я хочу, чтобы упростить JSON формат и использование

"2013/10" 

вместо этого, но оставьте мою модель без изменений. Как это сделать с Аргонавтом?

ответ

2

Нижняя часть манжеты, но она должна работать. Обратите внимание, что я предполагаю, что вы просто хотите пустую строку, по обе стороны от делителя, когда это значение пусто, и я не подтверждения того, что значение месяца находится между 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, но с ними также довольно легко работать.

+0

Именно то, что я искал. Спасибо, Трэвис. '' 'оператор также является удивительным для меня. – Tvaroh

Смежные вопросы