Spray-json DefaultJsonProtocol 带默认值
Spray-json DefaultJsonProtocol with default value
我在这个问题上看到了多个 post 但我没有找到任何解决方案来避免传递默认值。我有以下代码:
trait Message
case class StringMessag(msg:String) extends Message
case class PersonalMessage(msg:String, from:String, to:String) extends Message
我想在 httprequest 处理期间编组和取消编组。我遵循了多个论坛中描述的方法:
我修改了案例 classes 以添加类型如下:
case class StringMessag(msg:String, val kind:String="String") extends Message
case class PersonalMessage(msg:String, from:String, to:String, val kind:String="Personal") extends Message
implicit val stringMessageFormat = jsonFormat2(StringMessage.apply)
implicit val personalMessageFormat = jsonFormat4(PersonalMessage.apply)
implicit object MyJsonFormat extends RootJsonFormat[Message] {
def write(a: Message) = a match {
case a: StringMessage => a.toJson
case b: PersonalMessage => b.toJson
}
def read(value: JsValue) =
value.asJsObject.fields("kind") match {
case JsString("String") => value.convertTo[StringMessage]
case JsString("Personal") => value.convertTo[PersonalMessage]
}
}
这工作正常,但客户端程序必须为 "kind" 发送额外的默认值,即使 kind 在 class 的情况下定义了默认值。我们不能避免客户端传递额外的值,以便 RouteDSL 可以无错误地解组吗?
我尝试了以下解决方案;哪个有效,但看起来会更干净。
case class StringMessag(msg:String) extends Message
case class PersonalMessage(msg:String, from:String, to:String) extends Message
implicit val stringMessageFormat = jsonFormat1(StringMessage.apply)
implicit val personalMessageFormat = jsonFormat3(PersonalMessage.apply)
def read(value: JsValue) =
value match {
case obj:JsObject if(obj.fields.size==1 && obj.fields.contains("msg")) => value.convertTo[StringMessage]
case obj:JsObject if(obj.fields.size==3 && obj.fields.contains("from")) => value.convertTo[PersonalMessage]
}
谢谢
阿伦
我会定义一个自定义 JsonFormat[Message]
实例,其中为每种消息类型自动生成格式。在写入方法中,我会使用自动生成的格式进行模式匹配和写入 json,在读取方法中,我会尝试用自动生成的格式一个一个地解析 json,并且 return 第一个成功的结果.
这是一个示例实现
implicit object MessageFormat extends JsonFormat[Message] {
val stringMessageFormat = jsonFormat1(StringMessage)
val personalMessageFormat = jsonFormat3(PersonalMessage)
def write(obj: Message): JsValue = obj match {
case x: StringMessage => x.toJson
case x: PersonalMessage => x.toJson
}
def read(json: JsValue): Message =
Try(personalMessageFormat.read(json))
.orElse(Try(stringMessageFormat.read(json)))
.getOrElse(deserializationError(s"Invalid message format: ${json.toString()}"))
}
我在这个问题上看到了多个 post 但我没有找到任何解决方案来避免传递默认值。我有以下代码:
trait Message
case class StringMessag(msg:String) extends Message
case class PersonalMessage(msg:String, from:String, to:String) extends Message
我想在 httprequest 处理期间编组和取消编组。我遵循了多个论坛中描述的方法:
我修改了案例 classes 以添加类型如下:
case class StringMessag(msg:String, val kind:String="String") extends Message
case class PersonalMessage(msg:String, from:String, to:String, val kind:String="Personal") extends Message
implicit val stringMessageFormat = jsonFormat2(StringMessage.apply)
implicit val personalMessageFormat = jsonFormat4(PersonalMessage.apply)
implicit object MyJsonFormat extends RootJsonFormat[Message] {
def write(a: Message) = a match {
case a: StringMessage => a.toJson
case b: PersonalMessage => b.toJson
}
def read(value: JsValue) =
value.asJsObject.fields("kind") match {
case JsString("String") => value.convertTo[StringMessage]
case JsString("Personal") => value.convertTo[PersonalMessage]
}
}
这工作正常,但客户端程序必须为 "kind" 发送额外的默认值,即使 kind 在 class 的情况下定义了默认值。我们不能避免客户端传递额外的值,以便 RouteDSL 可以无错误地解组吗?
我尝试了以下解决方案;哪个有效,但看起来会更干净。
case class StringMessag(msg:String) extends Message
case class PersonalMessage(msg:String, from:String, to:String) extends Message
implicit val stringMessageFormat = jsonFormat1(StringMessage.apply)
implicit val personalMessageFormat = jsonFormat3(PersonalMessage.apply)
def read(value: JsValue) =
value match {
case obj:JsObject if(obj.fields.size==1 && obj.fields.contains("msg")) => value.convertTo[StringMessage]
case obj:JsObject if(obj.fields.size==3 && obj.fields.contains("from")) => value.convertTo[PersonalMessage]
}
谢谢 阿伦
我会定义一个自定义 JsonFormat[Message]
实例,其中为每种消息类型自动生成格式。在写入方法中,我会使用自动生成的格式进行模式匹配和写入 json,在读取方法中,我会尝试用自动生成的格式一个一个地解析 json,并且 return 第一个成功的结果.
这是一个示例实现
implicit object MessageFormat extends JsonFormat[Message] {
val stringMessageFormat = jsonFormat1(StringMessage)
val personalMessageFormat = jsonFormat3(PersonalMessage)
def write(obj: Message): JsValue = obj match {
case x: StringMessage => x.toJson
case x: PersonalMessage => x.toJson
}
def read(json: JsValue): Message =
Try(personalMessageFormat.read(json))
.orElse(Try(stringMessageFormat.read(json)))
.getOrElse(deserializationError(s"Invalid message format: ${json.toString()}"))
}