gpt4 book ai didi

scala - 如何使用 Reads 对 JsValue 进行模式匹配

转载 作者:行者123 更新时间:2023-12-02 19:58:14 26 4
gpt4 key购买 nike

我有一个 actor 在 play 2.3 中从 websocket 接收 JsValue。我还有一个定义 Reads 转换器的案例类。当我尝试针对案例类进行模式匹配时,它始终与 JsValue 而不是案例类匹配。

case class Ack(messageType: String, messageId: Int){
implicit val ackReads: Reads[Ack] = (
(JsPath \ "message_type").read[String] and
(JsPath \ "message_id").read[Int]
)(Ack.apply _)
}


class ChannelActor(out: ActorRef) extends Actor{
def receive = {
case a: Ack =>
println(s"Acknowledged! $a")
case msg: JsValue =>
println("Got other jsvalue")
case _ =>
println("Got something else")
}
}

如何将我从 websocket 接收到的 JsValue 与案例类中的 Reads 验证器进行模式匹配?

编辑:我找到了一种方法来解决这个问题,通过手动模式匹配 JsValue 来找出我需要验证的类型。代码现在看起来像这样:

case class Ack(messageType: String, messageId: Int)
object Ack{
implicit val ackReads: Reads[Ack] = (
(JsPath \ "message_type").read[String](verifying[String](_ == "ack")) and
(JsPath \ "message_id").read[Int]
)(Ack.apply _)

implicit val ackWrites: Writes[Ack] = (
(JsPath \ "message_type").write[String] and
(JsPath \ "message_id").write[Int]
)(unlift(Ack.unapply))
}


class ChannelActor(out: ActorRef) extends Actor{
def receive = {
case msg: JsValue =>
(msg \ "message_type").asOpt[String] match {
case Some("ack") =>
msg.validate[Ack] match{
case ack: JsSuccess[Ack] => println("got valid ack message")
case e: JsError => out ! Json.obj("error" -> s"invalid format for ack message ${JsError.toFlatJson(e).toString()}")
}
case None => out ! Json.obj("error" -> "you must send a message_type with your json object")
case t => out ! Json.obj("error" -> s"unknown message type ${t.get}")
}
case _ => out ! Json.obj("error" -> "unknown message format")
}
}

这实现了我想要的,但我感觉这不是在 Play 中验证 JSON 消息的“正确”或最优雅的解决方案,并且当我实现更多消息类型时会变得困惑。

最佳答案

参见http://www.playframework.com/documentation/2.3.x/ScalaWebSockets

它在文档中逐字记录

import play.api.libs.json._

implicit val inEventFormat = Json.format[InEvent]
implicit val outEventFormat = Json.format[OutEvent]

import play.api.mvc.WebSocket.FrameFormatter

implicit val inEventFrameFormatter = FrameFormatter.jsonFrame[InEvent]
implicit val outEventFrameFormatter = FrameFormatter.jsonFrame[OutEvent]

import play.api.mvc._
import play.api.Play.current

def socket = WebSocket.acceptWithActor[InEvent, OutEvent] { request => out =>
MyWebSocketActor.props(out)
}

编辑:好的,明白了。问题是 Json.format 写入方法不提供有关类型的信息。让我更深入地了解一下。

例如

case class Test(a: String)
implicit val f = Json.format[Test]
f.writes(Test1("hey")) // >> {"a":"hey"} note nothing says it's a Test1 instances

关于scala - 如何使用 Reads 对 JsValue 进行模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25223619/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com