5

Próbuję napisać niestandardowy serializator json za pomocą składni funkcjonalnej i nie mogę znaleźć odpowiedniego rozwiązania tego konkretnego problemu. Mam kilka obiektów DateTime joda, które chcę napisać w określonym formacie dla interfejsu użytkownika, który je zużywa. Czy ktoś może mi pokazać, gdzie się nie udało?scala play 2.1.1 json funkcjonalne dane mapowania składni do innego formatu

Oto klasa przypadku, z którą mam do czynienia w tej chwili, nic szczególnego się nie dzieje.

case class Banner(
    id: Int = 0, 
    ownerId: Int = 0, 
    licenseeId: Option[Int] = None, 
    statusColor: Option[String] = None, 
    content: Option[String] = None, 
    displayStart: DateTime = new DateTime(), 
    displayEnd: DateTime = new DateTime(), 
    created: DateTime = new DateTime(), 
    updated: DateTime = new DateTime() 
) 

Oto mój import do obiektu serializera.

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

pierwsze, Joda DateTime zamienia się długa dobrze niejawnie więc makro ekspander działa świetnie, czy to wszystko, co chciałem.

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

Potrzebuję przekonwertować obiekt displayStart i displayEnd na konkretny format ciągu, a nie na długą. To właśnie próbowałem zrobić.

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

Ale kompilator nie jest z tego zadowolony, więc nie wydaje się zrozumieć właściwy sposób korzystania z funkcji 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]        ^

Każda rada jest doceniana.

Odpowiedz

5

Udało mi się uzyskać ten jeden wymyślił, użyłem niewłaściwy typ operacji map functor i miał typy, które pracowałem z tyłu. Oto działa czyta/zapisuje implementacje w znacznie ładniejszej funkcjonalnej składni.

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

dlaczego nie można użyć '.format' zamiast' .read' + '.write'? –

2

Jestem zdecydowanie nie ekspert na ten temat, ale jestem całkiem pewny sposób korzystania inmap jest kombinacją jak używasz contramap/FMap.

czyli:

implicit val formatBanner = (
<truncated> 
    (__ \ "displayStart").format[String].inmap(DateTime.parse(_, userDateFormatter), userDateFormatter.print(_)) and 
<truncated> 
)(Banner.apply, unlift(Banner.unapply)) 
Powiązane problemy