自定义 spray-json RootJsonFormat 或 JsonFormat 取决于 JSON 对象中的值
Custom spray-json RootJsonFormat or JsonFormat depending on value in JSON object
在 Akka 流连接中,我收到 JSON 个如下所示的对象:
{"op":"connection"...}
{"op":"status"...}
..etc
我有以下 类 设置:
case class ResponseMessage(
op: Option[OpType],
)
case class ConnectionMessage(
a: Option[Int],
b: Option[Int],
) extends ResponseMessage
case class StatusMessage(
c: Option[Int],
d: Option[Int],
) extends ResponseMessage
type OpTypes = OpTypes.Value
object OpTypes extends Enumeration {
val Connection = Value("connection")
val Status = Value("status")
How can I write custom JsonFormat instances so that depending on the
value of op
I create the correct type?
So that it can be used as such:
> jsValue.convertTo[ResponseMessage] And the outvalue will be either
> ConnectionMessage or StatusMessage?
注意:扩展 case class 即 ResponseMessage 不是最佳做法。 Google "case class inheritance"...
关于你关于 JsonFormat
的问题,我会为每个子 class 定义特定的 JsonFormat
,然后根据类似的那些为 ResponseMessage
定义一个:
import spray.json._
abstract class ResponseMessage(val op: Option[OpTypes])
object ResponseMessage {
implicit object jsonFormat extends JsonFormat[ResponseMessage] {
override def read(json: JsValue): ResponseMessage = json match {
case JsObject(fields) =>
fields.get("op") match {
case Some(JsString("connection")) => json.convertTo[ConnectionMessage]
case Some(JsString("status")) => json.convertTo[StatusMessage]
case op => // unknown op
}
case _ => // invalid json
}
override def write(obj: ResponseMessage): JsValue = obj match {
case connection: ConnectionMessage => connection.toJson
case status: StatusMessage => status.toJson
}
}
}
case class ConnectionMessage(
a: Option[Int],
b: Option[Int]
) extends ResponseMessage(Some(OpTypes.Connection))
object ConnectionMessage {
implicit object jsonFormat extends JsonFormat[ConnectionMessage] {
override def read(json: JsValue): ConnectionMessage =
// json -> ConnectionMessage
override def write(obj: ConnectionMessage): JsValue =
// ConnectionMessage -> json
}
}
case class StatusMessage(
c: Option[Int],
d: Option[Int]
) extends ResponseMessage(Some(OpTypes.Status))
object StatusMessage {
implicit object jsonFormat extends JsonFormat[StatusMessage] {
override def read(json: JsValue): StatusMessage =
// json -> StatusMessage
override def write(obj: StatusMessage): JsValue =
// StatusMessage -> json
}
}
type OpTypes = OpTypes.Value
object OpTypes extends Enumeration {
val Connection = Value("connection")
val Status = Value("status")
}
在 Akka 流连接中,我收到 JSON 个如下所示的对象:
{"op":"connection"...}
{"op":"status"...}
..etc
我有以下 类 设置:
case class ResponseMessage(
op: Option[OpType],
)
case class ConnectionMessage(
a: Option[Int],
b: Option[Int],
) extends ResponseMessage
case class StatusMessage(
c: Option[Int],
d: Option[Int],
) extends ResponseMessage
type OpTypes = OpTypes.Value
object OpTypes extends Enumeration {
val Connection = Value("connection")
val Status = Value("status")
How can I write custom JsonFormat instances so that depending on the value of
op
I create the correct type? So that it can be used as such:
> jsValue.convertTo[ResponseMessage] And the outvalue will be either
> ConnectionMessage or StatusMessage?
注意:扩展 case class 即 ResponseMessage 不是最佳做法。 Google "case class inheritance"...
关于你关于 JsonFormat
的问题,我会为每个子 class 定义特定的 JsonFormat
,然后根据类似的那些为 ResponseMessage
定义一个:
import spray.json._
abstract class ResponseMessage(val op: Option[OpTypes])
object ResponseMessage {
implicit object jsonFormat extends JsonFormat[ResponseMessage] {
override def read(json: JsValue): ResponseMessage = json match {
case JsObject(fields) =>
fields.get("op") match {
case Some(JsString("connection")) => json.convertTo[ConnectionMessage]
case Some(JsString("status")) => json.convertTo[StatusMessage]
case op => // unknown op
}
case _ => // invalid json
}
override def write(obj: ResponseMessage): JsValue = obj match {
case connection: ConnectionMessage => connection.toJson
case status: StatusMessage => status.toJson
}
}
}
case class ConnectionMessage(
a: Option[Int],
b: Option[Int]
) extends ResponseMessage(Some(OpTypes.Connection))
object ConnectionMessage {
implicit object jsonFormat extends JsonFormat[ConnectionMessage] {
override def read(json: JsValue): ConnectionMessage =
// json -> ConnectionMessage
override def write(obj: ConnectionMessage): JsValue =
// ConnectionMessage -> json
}
}
case class StatusMessage(
c: Option[Int],
d: Option[Int]
) extends ResponseMessage(Some(OpTypes.Status))
object StatusMessage {
implicit object jsonFormat extends JsonFormat[StatusMessage] {
override def read(json: JsValue): StatusMessage =
// json -> StatusMessage
override def write(obj: StatusMessage): JsValue =
// StatusMessage -> json
}
}
type OpTypes = OpTypes.Value
object OpTypes extends Enumeration {
val Connection = Value("connection")
val Status = Value("status")
}