swift – 使Vapor API响应符合JSON API规范
我有一个用Vapor编写的API.我想按照
JSON API规范.
我正在努力理解如何以正确的格式创建我的响应对象. 例如,我希望我的回复结构如此…… { "links": { "self": "http://example.com/dish","next": "http://example.com/dish?page=2","last": "http://example.com/dish?page=10" },"data": [{ "title": "Spag Bol","course": "main","description": "BasGetti","price": 3.9900000000000002 },{ "title": "Ice Cream","course": "desert","description": "Vanilla","price": 0.98999999999999999 }] } 如果POST到此端点,我可以非常简单地返回数据的内容(伪代码) router.post(Dish.self,at: "api/dish") { req,data -> Future<Dish> in return Future.map(on: req,{ () -> Dish in data.id = 001 return data }) } 我尝试创建一个ApiResponse类并传入??数据,以便我可以构造响应,但这不适用于错误无法将类型’ApiResonse’的返回表达式转换为返回类型’Dish’ router.post(Dish.self,data -> Future<Dish> in return Future.map(on: req,{ () -> Dish in data.id = 001 return ApiResonse(links: Links(self: "http://google.com",next: "http://google.com",last: "http://google.com"),data: data) }) } 我不知道怎么能这样做.这些是尝试过的课程 final class Dish: Content { var id: Int? var title: String var description: String var course: String var price: Double init(title: String,description: String,course: String,price: Double) { self.title = title self.description = description self.course = course self.price = price } } struct Links { var `self`: String? var next: String? var last: String? } class ApiResonse { var links: Links? var data: Any init(links: Links,data: Any) { self.links = links self.data = data } } 我是否需要使用泛型来设置响应类?有人能提供一个例子吗? 解决方法
>复合对象ApiResponse中的每个类或结构都需要符合内容协议. Content协议包括用于JSON解码和编码的Codable协议.
>请注意,Any不符合Codable协议,因此Any不能用作Response的任何组成部分.有关更多详细信息,请参见 Vapor Docs: “Using Content”.
>完全符合Content的对象或复合对象可用作ResponseEncodable响应. 以下代码的示例项目位于GitHub: VaporExamplesLab/Example-SO-VaporJsonResponse. 示例模型 struct Dish: Content { var id: Int? var title: String var description: String var course: String var price: Double init(id: Int? = nil,title: String,price: Double) { self.id = id self.title = title self.description = description self.course = course self.price = price } } struct Links: Content { var current: String? var next: String? var last: String? } struct ApiResponse: Content { var links: Links? var dishes: [Dish] init(links: Links,dishes: [Dish]) { self.links = links self.dishes = dishes } } 示例POST:返回ApiResponse router.post(Dish.self,at: "api/dish") { (request: Request,dish: Dish) -> ApiResponse in var dishMutable = dish dishMutable.id = 001 var links = Links() links.current = "http://example.com" links.next = "http://example.com" links.last = "http://example.com" return ApiResponse(links: links,dishes: [dishMutable]) } 示例POST:返回Future< ApiResponse> router.post(Dish.self,at: "api/dish-future") { (request: Request,dish: Dish) -> Future<ApiResponse> in var dishMutable = dish dishMutable.id = 002 var links = Links() links.current = "http://example.com" links.next = "http://example.com" links.last = "http://example.com" return Future.map(on: request,{ () -> ApiResponse in return ApiResponse(links: links,dishes: [dishMutable]) }) } 收到JSON响应 上述代码的Response主体产生以下内容: { "links": { "current": "http://example.com","next": "http://example.com","last": "http://example.com" },"dishes": [ { "id": 1,"title": "Aztec Salad","description": "Flavorful Southwestern ethos with sweet potatos and black beans.","course": "salad","price": 1.82 } ] } 通用模型 struct ApiResponseGeneric<T> : Content where T: Content { var links: Links? var data: T init(links: Links,data: T) { self.links = links self.data = data } } 具体路线终点 router.post(Dish.self,at: "api/dish-generic-future") { (request: Request,dish: Dish) -> Future<ApiResponseGeneric<[Dish]>> in var dishMutable = dish dishMutable.id = 004 var links = Links() links.current = "http://example.com" links.next = "http://example.com" links.last = "http://example.com" return Future.map(on: request,{ () -> ApiResponseGeneric<[Dish]> in return ApiResponseGeneric<[Dish]>(links: links,data: [dishMutable]) }) } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |