ZIO:如何返回JSON?[不是在ZIO Http中使用case类,而是使用schema来映射?]



我尝试在代码中直接获取JSON的主体,然后我想将其转换为Avro以写入kafka主题。

这是我的案例类代码:


import zhttp.http._
import zio._
import zhttp.http.{Http, Method, Request, Response, Status}
import zhttp.service.Server
import zio.json._
import zio.kafka._
import zio.kafka.serde.Serde
import zio.schema._

case class Experiments(experimentId: String,
variantId: String,
accountId: String,
deviceId: String,
date: Int)
//case class RootInterface (events: Seq[Experiments])

object Experiments {
implicit val encoder: JsonEncoder[Experiments] = DeriveJsonEncoder.gen[Experiments]
implicit val decoder: JsonDecoder[Experiments] = DeriveJsonDecoder.gen[Experiments]
implicit val codec: JsonCodec[Experiments] = DeriveJsonCodec.gen[Experiments]
implicit val schema: Schema[Experiments] = DeriveSchema.gen
}
object HttpService {
def apply(): Http[ExpEnvironment, Throwable, Request, Response] =
Http.collectZIO[Request] {
case req@(Method.POST -> !! / "zioCollector") =>
val c = req.body.asString.map(_.fromJson[Experiments])
for {
u <- req.body.asString.map(_.fromJson[Experiments])
r <- u match {
case Left(e) =>
ZIO.debug(s"Failed to parse the input: $e").as(
Response.text(e).setStatus(Status.BadRequest)
)
case Right(u) =>
println(s"$u +       =====")
ExpEnvironment.register(u)
.map(id => Response.text(id))
}
}
yield r
}
}
//  val experimentsSerde: Serde[Any, Experiments] = Serde.string.inmapM { string =>
//    //desericalization
//    ZIO.fromEither(string.fromJson[Experiments].left.map(errorMessage => new RuntimeException(errorMessage)))
//  } { theMatch =>
//    ZIO.effect(theMatch.toJson)
//
//  }
object ZioCollectorMain extends ZIOAppDefault {
def run: ZIO[Environment with ZIOAppArgs with Scope, Any, Any] = {
Server.start(
port = 9001,
http = HttpService()).provide(ZLayerExp.layer)
}
}

我正在调查小齐奥,但还没有成功,任何帮助都很感激!

我们也可以用架构来获得avro通用记录

这是我的json:

{"实验Id":"abc";,"variantId":"123〃;,"accountId":"123〃;,"deviceId":"123〃;,"日期":1664544365}

这个函数在Scala 3中对我有效(对不起,我没有包含所有代码,但应该足够了(:

import zio.*
import zio.Console.printLine
import zhttp.http.*
import zhttp.service.Server
import zio.json.*
...
case class Experiments(experimentId: String,
variantId: String,
accountId: String,
deviceId: String,
date: Int)
//case class RootInterface (events: Seq[Experiments])

object Experiments:
implicit val encoder: JsonEncoder[Experiments] = DeriveJsonEncoder.gen[Experiments]
implicit val decoder: JsonDecoder[Experiments] = DeriveJsonDecoder.gen[Experiments]
implicit val codec: JsonCodec[Experiments] = DeriveJsonCodec.gen[Experiments]
val postingExperiment: Http[Any, Throwable, Request, Response] =
Http.collectZIO[Request] {
case req@(Method.POST -> !! / "zioCollector") =>
//val c = req.body.asString.map(_.fromJson[Experiments])
val experimentsZIO = req.body.asString.map(_.fromJson[Experiments])
for {
experimentsOrError <- experimentsZIO
response <- experimentsOrError match {
case Left(e) => ZIO.debug(s"Failed to parse the input: $e").as(
Response.text(e).setStatus(Status.BadRequest)
)
case Right(experiments) => ZIO.succeed(Response.json(experiments.toJson))
}
}   yield response
}

我稍微修改了你的代码(你没有发布ExpEnvironment类(,它会返回发布到url的对象。

测试代码为:

import sttp.client3.{SimpleHttpClient, UriContext, basicRequest}
object TestExperiments:
def main(args: Array[String]): Unit =
val client = SimpleHttpClient()
//post request
val request = basicRequest
.post(uri"http://localhost:9009/zioCollector")
.body("{ "experimentId": "abc", "variantId": "123", "accountId": "123", "deviceId": "123", "date": 1664544365 }")
val response = client.send(request)
println(response.body)
val invalidJsonRequest = basicRequest
.post(uri"http://localhost:9009/zioCollector")
.body("{ "experimentId": "abc", "variantId": "123", "accountId": "123", "deviceId": "123", "date": 1664544365 ") // missing the closing bracket
val invalidJsonResponse = client.send(invalidJsonRequest)
println(invalidJsonResponse.body)

您必须将:"com.softwaremill.sttp.client3" %% "core" % "3.8.3"添加到您的sbt文件中。

build.sbt:

ThisBuild / scalaVersion     := "3.2.0"
ThisBuild / version          := "0.1.0-SNAPSHOT"
ThisBuild / organization     := "TestSpeed"
ThisBuild / organizationName := "example"
lazy val root = (project in file("."))
.settings(
name := "TestZio",
libraryDependencies ++= Seq(
"dev.zio" %% "zio" % "2.0.2",
"dev.zio"       %% "zio-json"       % "0.3.0-RC11",
"io.d11" %% "zhttp" % "2.0.0-RC11",
"dev.zio" %% "zio-test" % "2.0.2" % Test,
"com.softwaremill.sttp.client3" %% "core" % "3.8.3" % Test
),
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
)

我没有包括任何与avro有关的内容,因为我不熟悉它。

相关内容

  • 没有找到相关文章

最新更新