gpt4 book ai didi

swift - 使 Vapor API 响应符合 JSON API 规范

转载 作者:搜寻专家 更新时间:2023-10-30 22:29:20 24 4
gpt4 key购买 nike

我有一个用 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 类并传入数据,这样我就可以构建响应,但这并没有解决错误 Cannot convert return expression of type 'ApiResonse' to return type '菜'

   router.post(Dish.self, at: "api/dish") { req, 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)
})
}

我不确定我该怎么做。这些是尝试过的类(class)

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
}
}

我是否需要使用泛型来设置响应类?谁能举个例子?

最佳答案

  1. 每个 classstruct在复合对象中 ApiResponse需要遵守 Content协议(protocol)。 Content协议(protocol)包括 Codable JSON解码和编码协议(protocol)。

  2. 注意 Any 符合Codable协议(protocol),因此 Any 不能用作响应的任何组成部分。参见 Vapor 3 Docs: "Using Content"Vapor 4 Docs: "Content"获取更多详细信息。

    Vapor 3: all content types (JSON, protobuf, URLEncodedForm, Multipart, etc) are treated the same. All you need to parse and serialize content is a Codable class or struct.

    Vapor 4: Vapor's content API allows you to easily encode / decode Codable structs to / from HTTP messages.

  3. 完全符合 Content 的对象或复合对象可以用作 ResponseEncodable响应。

  4. ApiResponse当每个路由端点解析为特定的 Content 时,模型可以是通用的协议(protocol)兼容类型

带有以下代码的示例项目在 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, description: String, course: 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 响应

上述代码的响应主体产生以下内容:

{
"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])
})
}

关于swift - 使 Vapor API 响应符合 JSON API 规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52232746/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com