问题描述
我有一个接受Either
的值类,我想为其生成Play for Scala v2.5.6 JSON Format
:
import org.joda.time.{DateTime, Duration}
case class When(when: Either[DateTime, Duration]) extends AnyVal
我想我已经找到了writes
方法;我遇到的问题是reads
方法.我尝试了两种方法,但都因不同的原因而失败.
尝试#1,同时显示reads
和writes
方法:
import play.api.libs.json._
import play.api.libs.json.Json.obj
object When {
def apply(dateTime: DateTime): When = When(Left(dateTime))
def apply(duration: Duration): When = When(Right(duration))
implicit val whenFormat = new Format[When] {
def reads(json: JsValue): JsResult[When] = {
val reads = (__ \ "dateTime").read[Long] { (millis: Long) =>
When(Left(new DateTime(millis)))
} | (__ \ "duration").read[Long] { (millis: Long) =>
When(Right(new Duration(millis)))
}
reads.reads(json)
}
def writes(o: When): JsValue = obj(
o.when.fold(
duration => "duration" -> duration.getMillis,
dateTime => "dateTime" -> dateTime.getMillis
)
)
}
}
错误消息是:
overloaded method value read with alternatives:
[error] (t: Long)play.api.libs.json.Reads[Long] <and>
[error] (implicit r: play.api.libs.json.Reads[Long])play.api.libs.json.Reads[Long]
[error] cannot be applied to (Long => When)
[error] val reads = (__ \ "dateTime").read[Long] { (millis: Long) =>
[error] overloaded method value read with alternatives:
[error] (t: Long)play.api.libs.json.Reads[Long] <and>
[error] (implicit r: play.api.libs.json.Reads[Long])play.api.libs.json.Reads[Long]
[error] cannot be applied to (Long => When)
[error] } | (__ \ "duration").read[Long] { (millis: Long) =>
尝试#2,仅显示reads
方法:
def reads(json: JsValue): JsResult[When] =
JsSuccess(
When(Left(new DateTime((__ \ "dateTime").read[Long]))) ||
When(Right(new Duration((__ \ "duration").read[Long])))
)
错误消息是:
value || is not a member of When
[error] Note: implicit value whenFormat is not applicable here because it comes after the application point and it lacks an explicit result type
[error] Error occurred in an application involving default arguments.
我只喜欢一种可行的方法,并且我不在乎使用哪种方法(即使我没有显示),只要它是可维护且高效的即可.了解这些方法中的每种方法有什么用也很有帮助.
以下是如何执行此操作的示例:
import org.joda.time.{DateTime, Duration}
import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._
import play.api.libs.json._
object When {
def apply(dateTime: DateTime): When = When(Left(dateTime))
def apply(duration: Duration): When = When(Right(duration))
val reads: Reads[When] =
(__ \ "dateTime").read[Long].map(millis => When(Left(new DateTime(millis)))) |
(__ \ "duration").read[Long].map(millis => When(Right(new Duration(millis))))
val writes: Writes[When] = new Writes[When] {
override def writes(o: When): JsValue = Json.obj(
o.when.fold(
duration => "duration" -> duration.getMillis,
dateTime => "dateTime" -> dateTime.getMillis
)
)
}
implicit val format = Format(reads, writes)
}
基本上,您应该映射阅读
(__ \ "dateTime").read[Long]
给出Reads[Long]
,然后您可以将结果映射到When
.您只是传递参数.此参数可以是Long
,只是忽略读取的内容并返回该值,或者implicit
长时间读取的内容可能不希望更改,并且应使其保持隐式.
因此,您可以类似的方式在持续时间内创建另一个读取,并将它们与替代(|
)组合在一起,然后完成读取.
您的第二种方法没有任何意义.使用读取并编写它们,或者只是手动检查是否有东西,如果没有返回不同的结果,但是这样做不值得,只需采用默认方法即可.
I have a value class that accepts an Either
, which I would like to generate a Play for Scala v2.5.6 JSON Format
for:
import org.joda.time.{DateTime, Duration}
case class When(when: Either[DateTime, Duration]) extends AnyVal
I think I have the writes
method figured out; the problems I am having are with the reads
method. I've attempted two approaches, both failed for different reasons.
Attempt #1, showing both the reads
and writes
methods:
import play.api.libs.json._
import play.api.libs.json.Json.obj
object When {
def apply(dateTime: DateTime): When = When(Left(dateTime))
def apply(duration: Duration): When = When(Right(duration))
implicit val whenFormat = new Format[When] {
def reads(json: JsValue): JsResult[When] = {
val reads = (__ \ "dateTime").read[Long] { (millis: Long) =>
When(Left(new DateTime(millis)))
} | (__ \ "duration").read[Long] { (millis: Long) =>
When(Right(new Duration(millis)))
}
reads.reads(json)
}
def writes(o: When): JsValue = obj(
o.when.fold(
duration => "duration" -> duration.getMillis,
dateTime => "dateTime" -> dateTime.getMillis
)
)
}
}
The error messages are:
overloaded method value read with alternatives:
[error] (t: Long)play.api.libs.json.Reads[Long] <and>
[error] (implicit r: play.api.libs.json.Reads[Long])play.api.libs.json.Reads[Long]
[error] cannot be applied to (Long => When)
[error] val reads = (__ \ "dateTime").read[Long] { (millis: Long) =>
[error] overloaded method value read with alternatives:
[error] (t: Long)play.api.libs.json.Reads[Long] <and>
[error] (implicit r: play.api.libs.json.Reads[Long])play.api.libs.json.Reads[Long]
[error] cannot be applied to (Long => When)
[error] } | (__ \ "duration").read[Long] { (millis: Long) =>
Attempt #2, just showing the reads
method:
def reads(json: JsValue): JsResult[When] =
JsSuccess(
When(Left(new DateTime((__ \ "dateTime").read[Long]))) ||
When(Right(new Duration((__ \ "duration").read[Long])))
)
The error message is:
value || is not a member of When
[error] Note: implicit value whenFormat is not applicable here because it comes after the application point and it lacks an explicit result type
[error] Error occurred in an application involving default arguments.
I'd just like something that works, and I don't care what approach is used (even one I did not show), so long as it is maintainable and efficient. It would also be helpful to know what was wrong with each of these approaches.
Here is working example of how to do this:
import org.joda.time.{DateTime, Duration}
import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._
import play.api.libs.json._
object When {
def apply(dateTime: DateTime): When = When(Left(dateTime))
def apply(duration: Duration): When = When(Right(duration))
val reads: Reads[When] =
(__ \ "dateTime").read[Long].map(millis => When(Left(new DateTime(millis)))) |
(__ \ "duration").read[Long].map(millis => When(Right(new Duration(millis))))
val writes: Writes[When] = new Writes[When] {
override def writes(o: When): JsValue = Json.obj(
o.when.fold(
duration => "duration" -> duration.getMillis,
dateTime => "dateTime" -> dateTime.getMillis
)
)
}
implicit val format = Format(reads, writes)
}
basically you should map the reads
(__ \ "dateTime").read[Long]
gives you Reads[Long]
, then you can map result to When
. You were just passing parameter. This parameter could be a Long
, to just ignore what is read and return that value, or implicit
reads for long that you probably don't want to change and should let it stay implicit.
So then in similar way you can create another reads for duration and combine them with alternative (|
) and done, you have reads.
Your second approach makes no sense. Either use reads and compose them or just manually check if something is there and if not return a different result, but it is not worth doing this, just go with default approach.
这篇关于两者的播放/Scala JSON格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!