2013-10-24 5 views
2

모델 :모험가, 사용자 정의 JSON 형식 매핑

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

모험가 기반 디코더 :

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

지금 내가 JSON을 단순화 할 :

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

이 같은 형식을 구문 분석 할 수 있습니다 형식 및 사용

"2013/10" 

대신 내 모델을 변경하지 마십시오. Argonaut와 함께이 작업을 수행하는 방법은 무엇입니까?

답변

2

다음은 팔목에서 떨어져 있지만 작동해야합니다. 난 당신이 그냥 값이 비어 디바이더의 양쪽에 빈 문자열을 원하는 있으리라 믿고있어, 나는 달의 값입니다 확인하는 게 아니에요 있습니다

그리고

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) 
    } 
) 

1 ~ 12 : 우리를 제공

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