gpt4 book ai didi

scala - 使用 Play WSClient 处理 JSON 错误响应

转载 作者:行者123 更新时间:2023-12-03 07:38:16 28 4
gpt4 key购买 nike

我正在使用 Play 的 WSClient 与第三方服务进行交互

request = ws.url(baseUrl)
.post(data)
.map{ response =>
response.json.validate[MyResponseClass]

响应可能是 MyResponseClass或者它可能是 ErrorResponse喜欢 { "error": [ { "message": "Error message" } ] }
是否有一种典型的方法来解析类 错误?

我应该做这样的事情吗?
response.json.validateOpt[MyResponseClass].getOrElse(response.json.validateOpt[ErrorClass])

最佳答案

这个问题没有唯一的答案。这里有多个微妙的考虑。我的回答将尝试提供一些方向。

至少要处理四种不同的情况 :

  • 应用程序级别的有效结果(已建立连接、收到响应、200 状态代码)
  • 应用程序级错误(已建立连接、收到响应、4xx、5xx 状态代码)
  • 网络 IO 错误(未建立连接,或由于超时等原因未收到响应)
  • JSON 解析错误(建立连接、收到响应、无法将 JSON 转换为模型域对象)

  • 伪代码 :
  • 已完成 Future里面的响应是 ErrorResponseMyResponseClass ,即 Either[ErrorResponse, MyResponseClass] :
  • 如果服务返回 200 状态码,则解析为 MyResponseClass
  • 如果服务返回 >= 400 状态码,则解析为 ErrorResponse
  • 已完成 Future除了里面:
  • 解析异常,或
  • 网络 IO 异常(例如超时)

  • Future(Left(errorResponse))对比 Future(throw new Exception)

    注意 Future(Left(errorResponse))之间的区别和 Future(throw new Exception) :我们只将后者视为 failed future .前者,尽管有 Left里面还是考虑一个顺利完成的 future 。

    Future.andThen对比 Future.recover

    注意 Future.andThen 之间的区别和 Future.recover : 前者不会改变future里面的值,而后者可以改变里面的值和它的类型。如果无法恢复,我们至少可以使用 andThen 记录异常。 .

    示例 :
    import akka.actor.ActorSystem
    import akka.stream.ActorMaterializer
    import play.api.libs.ws._
    import play.api.libs.ws.ahc._
    import scala.concurrent.ExecutionContext.Implicits._
    import scala.concurrent.Future
    import play.api.libs.json._
    import play.api.libs.ws.JsonBodyReadables._
    import scala.util.Failure
    import java.io.IOException
    import com.fasterxml.jackson.core.JsonParseException

    case class ErrorMessage(message: String)

    object ErrorMessage {
    implicit val errorMessageFormat = Json.format[ErrorMessage]
    }

    case class ErrorResponse(error: List[ErrorMessage])

    object ErrorResponse {
    implicit val errorResponseFormat = Json.format[ErrorResponse]
    }

    case class MyResponseClass(a: String, b: String)

    object MyResponseClass {
    implicit val myResponseClassFormat = Json.format[MyResponseClass]
    }

    object PlayWsErrorHandling extends App {
    implicit val system = ActorSystem()
    implicit val materializer = ActorMaterializer()

    val wsClient = StandaloneAhcWSClient()

    httpRequest(wsClient) map {
    case Left(errorResponse) =>
    println(s"handle application level error: $errorResponse")
    // ...

    case Right(goodResponse) =>
    println(s"handle application level good response $goodResponse")
    // ...

    } recover { // handle failed futures (futures with exceptions inside)
    case parsingError: JsonParseException =>
    println(s"Attempt recovery from parsingError")
    // ...

    case networkingError: IOException =>
    println(s"Attempt recovery from networkingError")
    // ...
    }

    def httpRequest(wsClient: StandaloneWSClient): Future[Either[ErrorResponse, MyResponseClass]] =
    wsClient.url("http://www.example.com").get() map { response ⇒

    if (response.status >= 400) // application level error
    Left(response.body[JsValue].as[ErrorResponse])
    else // application level good response
    Right(response.body[JsValue].as[MyResponseClass])

    } andThen { // exceptions thrown inside Future
    case Failure(exception) => exception match {
    case parsingError: JsonParseException => println(s"Log parsing error: $parsingError")
    case networkingError: IOException => println(s"Log networking errors: $networkingError")
    }
    }
    }

    依赖项:
    libraryDependencies ++= Seq(
    "com.typesafe.play" %% "play-ahc-ws-standalone" % "1.1.3",
    "com.typesafe.play" %% "play-ws-standalone-json" % "1.1.3"
    )

    关于scala - 使用 Play WSClient 处理 JSON 错误响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47210587/

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