当我试图创建一个具有多体形状的端点时,我只是在讨论一个问题。
我的模型看起来是这样的:
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)))))“}我在跟踪这文档。
发布于 2022-05-28 15:30:51
这是因为一个特征没有错误本身所指示的构造函数。我想我知道你要去哪里了,你想试着把身体解析为特征子类之一。因此,假设您有这样的类型/类层次结构:
T // parent trait
/ \
C1 C2 // class 1, etc...
/
C3现在您想要将一些JSON反序列化为特性T,您需要定义您的自定义行为,比如“首先尝试转换为C3,如果失败,尝试转换为C2,如果再次失败,尝试转换为C1",您将得到您的T值。现在,取决于您使用的JSON库,实现可能有所不同,请参阅软件轧机的文档,以获得更多关于如何在tapir中处理Json的信息,如果您使用Play Json,我可以推荐:
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,.)。
https://stackoverflow.com/questions/72415969
复制相似问题