首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用带有多个模式的Scala中的Tapir创建端点

如何使用带有多个模式的Scala中的Tapir创建端点
EN

Stack Overflow用户
提问于 2022-05-28 13:11:20
回答 1查看 334关注 0票数 1

当我试图创建一个具有多体形状的端点时,我只是在讨论一个问题。

我的模型看起来是这样的:

代码语言:javascript
复制
sealed trait FileExampleTrait {
  def kind: String
}

case class FileExampleOne(name: String, length: Int) extends FileExampleTrait {
  override def kind: String = “one”
}

case class FileExampleTwo(name: String) extends FileExampleTrait {
  override def kind: String = “two”
}

case class FileExampleResponse(message: String)

我正在尝试创建这个端点:

代码语言:javascript
复制
val fileExample = baseEndpoint.post
    .in(“example”)
    .in(jsonBody[FileExampleTrait])
    .out(jsonBody[FileExampleResponse])
    .summary(“something”)
    .description(“something”)

端点的实现如下所示:

代码语言:javascript
复制
private val fileExample = toAkkaRoute(jwtConsumer, errorHandler)(
    FileApi.fileExample, { (scope: RequestScope, input: (FileExampleTrait)) =>
      print(scope)
      input match {
        case FileExampleOne(name, _) => Future.successful(FileExampleResponse(name).asRight)
        case FileExampleTwo(name) => Future.successful(FileExampleResponse(name).asRight)
      }
    }
  )

这只是我试图创造的一个例子。我在此基础上添加了模式派生:

代码语言:javascript
复制
  val sOne = Schema.derived[FileExampleOne]
  val sTwo = Schema.derived[FileExampleTwo]
  implicit val sExampleTrait: Schema[FileExampleTrait] =
    Schema.oneOfUsingField[FileExampleTrait, String](_.kind, _.toString)(“one” -> sOne, “two” -> sTwo)

我创建了一个基于Akka HTTP的端点测试:

代码语言:javascript
复制
   test(“Example test”) {
    new Fixture() {
      val request = FileExampleOne(“name”, 1)
      Post(s”/api/v1/files/example”, jsonEntity(request)).withHeaders(requestHeaders) ~> wrappedRoute ~> check {
        response should be(successful)
        contentType shouldEqual ContentTypes.`application/json`
      }
    }
  }

我得到的错误如下:

代码语言:javascript
复制
Response error: {“code”:400,“message”:“Invalid value for: body (No constructor for type FileExampleTrait, JObject(List((name,JString(name)), (length,JInt(1)))))“}

我在跟踪文档。

EN

回答 1

Stack Overflow用户

发布于 2022-05-28 15:30:51

这是因为一个特征没有错误本身所指示的构造函数。我想我知道你要去哪里了,你想试着把身体解析为特征子类之一。因此,假设您有这样的类型/类层次结构:

代码语言:javascript
复制
        T // parent trait
       / \
     C1  C2  // class 1, etc...
    /
  C3

现在您想要将一些JSON反序列化为特性T,您需要定义您的自定义行为,比如“首先尝试转换为C3,如果失败,尝试转换为C2,如果再次失败,尝试转换为C1",您将得到您的T值。现在,取决于您使用的JSON库,实现可能有所不同,请参阅软件轧机的文档,以获得更多关于如何在tapir中处理Json的信息,如果您使用Play Json,我可以推荐:

代码语言:javascript
复制
object FileExampleOne {
  implicit val reader: Reads[FileExampleOne] = Json.reads
}

object FileExampleTwo {
  implicit val reader: Reads[FileExampleTwo] = Json.reads
}

object FileExampleTrait {
  implicit val reads: Reads[FileExampleTrait] = json => {
    json.validate[FileExampleOne] orElse json.validate[FileExampleTwo]
  }
}

您可以看到它在鸡皮癣上运行。基于tapir文件,您需要为您的类型创建一个Codec,而为Json创建代码的方法之一是使用tapir支持的库之一(circe,Play JSON,.)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72415969

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档