5

기능적 구문을 사용하여 사용자 지정 json serializer를 작성하려고하는데이 특정 문제를 해결할 올바른 방법을 찾지 못하는 것 같습니다. 몇 가지 joda DateTime 개체를 그것을 소비하는 UI에 대한 특정 형식으로 쓰고 싶습니다. 누구든지 내가 잘못한 곳을 보여줄 수 있습니까?스칼라 플레이 2.1.1 json 기능 구문 데이터를 다른 형식으로 매핑

여기 제가 지금 다루고있는 사례 클래스입니다. 특별한 것은 없습니다.

다음은 serializer 객체에 대한 나의 import입니다.

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 
import org.joda.time.DateTime 
import org.joda.time.format.DateTimeFormat 

우선, 즉 내가 원하는 모든 인 경우에 매크로 확장이 잘 작동되도록 날짜 시간이 암시 적으로 긴 잘으로 변환하는 joda. 내가 필요로 무엇

object MySerializers { 
    implicit val writesBanner = Json.writes[Banner] 
} 

는 특정 문자열 형식이 아닌 긴 값으로 displayStart 및 displayEnd 객체를 변환하는 것입니다. 이것이 제가하려고 한 것입니다.

object MySerializers { 
    val userDateFormatter = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm a") 

    implicit val writesBanner = (
    (__ \ "id").write[Int] and 
    (__ \ "ownerId").write[Int] and 
    (__ \ "licenseeId").write[Int] and 
    (__ \ "statusColor").writeNullable[String] and 
    (__ \ "content").writeNullable[String] and 
    (__ \ "displayStart").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and 
    (__ \ "displayEnd").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and 
    (__ \ "created").write[DateTime] and 
    (__ \ "updated").write[DateTime] 
)(unlift(Banner.unapply)) 
} 

는하지만 컴파일러는 그것에 대해 행복하지 않다, 그래서 inmap 기능을 사용하는 올바른 방법을 이해하지 못하는 것 같습니다.

could not find implicit value for parameter fu: 
play.api.libs.functional.InvariantFunctor[play.api.libs.json.OWrites] 
[error]  (__ \ "displayStart").write[DateTime].inmap[String](dt =>  
userDateFormatter.print(dt)) and 
[error]        ^

모든 조언을 주시면 감사하겠습니다.

답변

5

필자는이 중 하나를 알아 냈습니다. 잘못된 유형의 펑터 맵 작업을 사용하고 있고, 내가 뒤로 작업하고있는 유형이있었습니다. 여기에 작동하는 읽기/쓰기 구현은 훨씬 멋진 구문 구문으로되어 있습니다.

implicit val writesBanner = (
    (__ \ "id").write[Int] and 
    (__ \ "ownerId").write[Int] and 
    (__ \ "licenseeId").writeNullable[Int] and 
    (__ \ "statusColor").writeNullable[String] and 
    (__ \ "content").writeNullable[String] and 
    (__ \ "displayStart").write[String].contramap[DateTime](dt => userDateFormatter.print(dt)) and 
    (__ \ "displayEnd").write[String].contramap[DateTime](dt => userDateFormatter.print(dt)) and 
    (__ \ "created").write[DateTime] and 
    (__ \ "updated").write[DateTime] 
)(unlift(Banner.unapply)) 

implicit val readsBanner = (
    (__ \ "id").read[Int] and 
    (__ \ "ownerId").read[Int] and 
    (__ \ "licenseeId").readNullable[Int] and 
    (__ \ "statusColor").readNullable[String] and 
    (__ \ "content").readNullable[String] and 
    (__ \ "displayStart").read[String].fmap[DateTime](dt => DateTime.parse(dt, userDateFormatter)) and 
    (__ \ "displayEnd").read[String].fmap[DateTime](dt => DateTime.parse(dt, userDateFormatter)) and 
    (__ \ "created").read[DateTime] and 
    (__ \ "updated").read[DateTime] 
)(Banner) 
+0

왜 당신은'대신 .format' 사용하지 않는'.read' +'.write'? –

2

은 확실히 이것에 전문가는 아니지만,하지만 난 당신이 inmap를 사용하는 방법은 당신이 contramap/fmap 함수를 사용하는 방법의 조합입니다 확신 해요. 되어

:

implicit val formatBanner = (
<truncated> 
    (__ \ "displayStart").format[String].inmap(DateTime.parse(_, userDateFormatter), userDateFormatter.print(_)) and 
<truncated> 
)(Banner.apply, unlift(Banner.unapply)) 
관련 문제