我只是在尝试创建具有多个几何体形状的端点时遇到了一个问题。
我的模型如下所示:
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)
我正在尝试创建这个端点:
val fileExample = baseEndpoint.post
.in(“example”)
.in(jsonBody[FileExampleTrait])
.out(jsonBody[FileExampleResponse])
.summary(“something”)
.description(“something”)
端点的实作如下所示:
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)
}
}
)
这只是我尝试创建的一个示例。我添加了基于此的模式派生:
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的端点:
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`
}
}
}
我得到的错误如下:
Response error: {“code”:400,“message”:“Invalid value for: body (No constructor for type FileExampleTrait, JObject(List((name,JString(name)), (length,JInt(1)))))“}
我一直在看这份文件。
1条答案
按热度按时间0tdrvxhp1#
这是因为trait本身没有构造函数,我想我明白你的意思了,你想把body解析成trait的子类,假设你有这样的类型/类层次结构:
现在您想将一些JSON反序列化为trait
T
,您需要定义自定义行为,如“首先尝试转换为C3,如果失败,尝试转换为C2,如果再次失败,尝试转换为C1”,然后您将获得T
值。现在,根据您使用的JSON库,实现可能会有所不同。请参阅softwaremill的documentation以获得有关如何在Tapir中处理JSON的更多信息,如果您使用Play Json,我可以推荐:你可以看到它在scastie上运行。基于tapir documentations,你需要一个
Codec
来支持你的类型,创建JSON代码的方法之一是使用tapir支持的库之一(circe,Play Json,...)。