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:
我有一个值类接受一个Either,我想生成一个Play for Scala v2.5.6 JSON格式:
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.
我想我已经找到了写法;我遇到的问题是read方法。我尝试了两种方法,都因为不同的原因而失败。
Attempt #1, showing both the reads
and writes
methods:
尝试#1,显示读写方法:
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:
尝试#2,只显示读取方法:
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.
我只是喜欢有用的东西,我不关心使用什么方法(即使是我没有展示的方法),只要它是可维护和有效的。知道每种方法的错误也会有所帮助。
1 个解决方案
#1
7
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.
给你Read [Long],然后你可以把结果映射到When。你只是传递参数。这个参数可以是Long,只是忽略读取的内容并返回该值,或者长时间隐式读取,你可能不想改变它应该让它保持隐含。
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.
你的第二种方法毫无意义。要么使用读取和组合它们,要么只是手动检查是否有东西,如果没有返回不同的结果,但是不值得这样做,只需采用默认方法。
#1
7
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.
给你Read [Long],然后你可以把结果映射到When。你只是传递参数。这个参数可以是Long,只是忽略读取的内容并返回该值,或者长时间隐式读取,你可能不想改变它应该让它保持隐含。
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.
你的第二种方法毫无意义。要么使用读取和组合它们,要么只是手动检查是否有东西,如果没有返回不同的结果,但是不值得这样做,只需采用默认方法。