Scala JSON 写入计算值
Scala JSON Writes with calculated values
我们正在使用 Play 的 JSON 序列化对模型进行序列化。
case class Foo(
var id: Long,
var birthday: Date,
[...]
)
object Foo {
implicit val fooFormat: OFormat[Foo] = Json.format[Foo]
}
但是我们想添加一些计算值,例如:
case class Foo(
...
) {
def age: Int = 32
}
为了在序列化中包含年龄,看来我们必须通过写出完整的 Writes/unapply 方法来复制所有字段名称:
implicit val fooWrites: Writes[Foo] = (
(JsPath \ "id").write[Long] and
(JsPath \ "birthday").write[Date] and
[...]
(JsPath \ "age").write[Int]
)(unlift(Foo.unapply_extended))
def unapply_extended(a: Foo): Option[(Long,Date,[...],Int)] = Some(( a.id, a.birthday, [...], a.age))
implicit val fooReads = Json.reads[Foo]
有没有办法将计算出的年龄值包含在 JSON 序列化中,而不必多次重新枚举相同的案例 class fields/types?当有很多字段时,它很快变得难以管理,所有信息都是多余的。
开箱即用我认为这是不可能的,因为生成的编解码器针对常见用例(案例 类 及其字段)进行了优化。但是您可以使用 transformers.
派生编解码器并在之后调整它们的行为
case class Foo(
...
) {
def age: Int = 32
}
object Foo {
implicit val fooFormat: OFormat[Foo] = {
val derived = Json.format[Foo] // majority of work done here
// here we just modify output of writer to add that one field
OFormat(
r = derived,
w = foo => Json.writes[Foo].transform { json: JsObject =>
json.transform((__ \ 'age).json.put(JsNumber(foo.age))).getOrElse(json)
}.writes(foo)
)
}
}
如果单独导出读取和写入,您可以节省一两行代码
object Foo {
implicit val fooFormat: OFormat[Foo] = OFormat(
r = Json.reads[Foo],
w = foo => Json.writes[Foo].transform { json: JsObject =>
json.transform((__ \ 'age).json.put(JsNumber(foo.age))).getOrElse(json)
}.writes(foo)
)
}
我们正在使用 Play 的 JSON 序列化对模型进行序列化。
case class Foo(
var id: Long,
var birthday: Date,
[...]
)
object Foo {
implicit val fooFormat: OFormat[Foo] = Json.format[Foo]
}
但是我们想添加一些计算值,例如:
case class Foo(
...
) {
def age: Int = 32
}
为了在序列化中包含年龄,看来我们必须通过写出完整的 Writes/unapply 方法来复制所有字段名称:
implicit val fooWrites: Writes[Foo] = (
(JsPath \ "id").write[Long] and
(JsPath \ "birthday").write[Date] and
[...]
(JsPath \ "age").write[Int]
)(unlift(Foo.unapply_extended))
def unapply_extended(a: Foo): Option[(Long,Date,[...],Int)] = Some(( a.id, a.birthday, [...], a.age))
implicit val fooReads = Json.reads[Foo]
有没有办法将计算出的年龄值包含在 JSON 序列化中,而不必多次重新枚举相同的案例 class fields/types?当有很多字段时,它很快变得难以管理,所有信息都是多余的。
开箱即用我认为这是不可能的,因为生成的编解码器针对常见用例(案例 类 及其字段)进行了优化。但是您可以使用 transformers.
派生编解码器并在之后调整它们的行为case class Foo(
...
) {
def age: Int = 32
}
object Foo {
implicit val fooFormat: OFormat[Foo] = {
val derived = Json.format[Foo] // majority of work done here
// here we just modify output of writer to add that one field
OFormat(
r = derived,
w = foo => Json.writes[Foo].transform { json: JsObject =>
json.transform((__ \ 'age).json.put(JsNumber(foo.age))).getOrElse(json)
}.writes(foo)
)
}
}
如果单独导出读取和写入,您可以节省一两行代码
object Foo {
implicit val fooFormat: OFormat[Foo] = OFormat(
r = Json.reads[Foo],
w = foo => Json.writes[Foo].transform { json: JsObject =>
json.transform((__ \ 'age).json.put(JsNumber(foo.age))).getOrElse(json)
}.writes(foo)
)
}