Play / Scala JSON 两种格式
Play / Scala JSON Format for Either
我有一个接受 Either
的值 class,我想为 Scala v2.5.6 JSON Format
生成一个 Play:
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
,只忽略读取的内容和 return 该值,或者 implicit
读取很长时间,您可能不想更改,应该让它保持隐式.
然后以类似的方式,您可以创建另一个持续时间的读取并将它们与替代 (|
) 结合起来,完成后,您已经读取了。
你的第二种方法没有意义。要么使用读取并组合它们,要么只是手动检查是否存在某些内容,如果不存在则 return 不同的结果,但不值得这样做,只需使用默认方法即可。
我有一个接受 Either
的值 class,我想为 Scala v2.5.6 JSON Format
生成一个 Play:
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
,只忽略读取的内容和 return 该值,或者 implicit
读取很长时间,您可能不想更改,应该让它保持隐式.
然后以类似的方式,您可以创建另一个持续时间的读取并将它们与替代 (|
) 结合起来,完成后,您已经读取了。
你的第二种方法没有意义。要么使用读取并组合它们,要么只是手动检查是否存在某些内容,如果不存在则 return 不同的结果,但不值得这样做,只需使用默认方法即可。