Swift Vapor 3解码内容:多个post格式的do/catch?
我有一个控制器,其创建操作我希望接受JSON,如下所示:Swift Vapor 3解码内容:多个post格式的do/catch?,swift,vapor,vapor-fluent,Swift,Vapor,Vapor Fluent,我有一个控制器,其创建操作我希望接受JSON,如下所示: { "foo": "bar" } { "widget": { "foo": "bar" } } 或者像这样: { "foo": "bar" } { "widget": { "foo": "bar" } } 也就是说,我想要接受小部件或包装在包含对象中的小部件。当前,“我的控制器”的创建操作看起来非常像: func createHandler(_ req: Request) throws -> Future<Widget
{ "foo": "bar" }
{ "widget": { "foo": "bar" } }
或者像这样:
{ "foo": "bar" }
{ "widget": { "foo": "bar" } }
也就是说,我想要接受小部件或包装在包含对象中的小部件。当前,“我的控制器”的创建操作看起来非常像:
func createHandler(_ req: Request) throws -> Future<Widget> {
do {
return try req.content.decode(WidgetCreateHolder.self).flatMap(to: Widget.self) {
return createWidget(from: $0.widget)
}
} catch DecodingError.keyNotFound {
return try req.content.decode(WidgetCreateObject.self).flatMap(to: Widget.self) {
return createWidget(from: $0)
}
}
}
其中WidgetCreateHolder
看起来像:
struct WidgetCreateHolder { var widget: WidgetCreateObject }
也就是说,我的创建操作应该尝试创建一个holder,但是如果失败,它应该捕获错误并尝试只创建内部对象(一个WidgetCreateObject
)。但是,当我将此代码部署到Heroku并仅使用内部对象JSON发出请求时,我会在日志中看到:
[ ERROR ] DecodingError.keyNotFound: Value required for key 'widget'. (ErrorMiddleware.swift:26)
即使我试图抓住那个错误
如何让我的创建操作接受两种不同格式的JSON对象?解决了这个问题
decode
方法返回一个Future
,这样实际的解码(以及由此产生的错误)会在以后发生,而不是在do/catch期间。这意味着无法使用此do catch捕捉错误
幸运的是,Future
s有一系列的方法,前面有catch
;我感兴趣的是catchFlatMap
,它接受来自Error->Future
的闭包。这个方法“捕获”在被调用的将来抛出的错误,并将错误传递给闭包,在任何下游的将来使用结果
因此,我可以将代码更改为:
func createHandler(_ req: Request) throws -> Future<Widget> {
return try req.content.decode(WidgetCreateHolder.self).catchFlatMap({ _ in
return try req.content.decode(WidgetCreateObject.self).map(to: WidgetCreateHolder.self) {
return WidgetCreateHolder(widget: $0)
}
}).flatMap(to: Widget.self) {
return createWidget(from: $0.widget)
}
}
func createHandler(\ureq:Request)抛出->未来{
返回try-req.content.decode(WidgetCreateHolder.self).catchFlatMap({in
返回try req.content.decode(WidgetCreateObject.self).map(到:WidgetCreateHolder.self){
返回WidgetCreateHolder(小部件:$0)
}
}).flatMap(到:Widget.self){
返回createWidget(发件人:$0.widget)
}
}
有两个结构都符合可解码的要求。让我们调用结构,其中widget为A1,而widget为A2。尝试将其解码为A1,如果失败,尝试将其解码为A2。在第一种情况下,使用map操作符将A1转换为A2。