首页 > 解决方案 > 如何将 URLSession 中的嵌套原始 JSON 发送到 Vapor API?

问题描述

我有一个 Vapor API,它有一个注册用户的路线。这条路线以 JSON 格式接收嵌套对象,如下所示:

{
    "name": "Test",
    "email": "test1@test.com",
    "password": "Test1",
    "phone": {
        "numberString": "+52 999 999 9999",
        "countryCode": 52,
        "nationalNumber": 9999999999,
    }
}

此 JSON 被转换为 Content/Codable 对象:

final class Create: Codable, Content {
    let name: String!
    let email: String!
    let password: String
    let phone: PhoneNumber!

    init(name: String, email: String, password: String, phone: PhoneNumber) {
        self.name = name
        self.email = email
        self.password = password
        self.phone = phone
    }
}

我已经尝试过通过 Postman 将 JSON 字符串作为原始字符串发送的这条路由,并且该路由运行良好,但问题是当我尝试通过 iOS 对应的 URLSession 发送它时,ErrorMiddleware 会引发 DecodingError:

DecodingError:键“密码”所需的“字符串”类型的值。

起初我认为问题在于 JSON 生成,直到出于测试目的,我发送了与示例中相同的 JSON,而 Vapor API 仍然抛出错误。

let urlStr = "\(BaseURL)/api/student/register"

guard let url = URL(string: urlStr) else { return }

var urlRequest = URLRequest(url: url, cachePolicy:
    .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0)


let raw = "{\"name\":\"Prueba\",\"email\":\"prueba1@hotmail.com\",\"password\":\"Prueba1\",\"phone\":{\"numberString\":\"+52 999 271 5671\",\"countryCode\":52,\"nationalNumber\":9992715671}}"

urlRequest.httpMethod = "POST"
urlRequest.httpBody = raw.data(using: .utf8)

urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")

URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
    ...
}.resume()

你甚至可以通过 URLSession 发送这种类型的 JSON,还是我需要更改我的逻辑以便它接收一个平面数组?

标签: jsonswiftvaporurlsession

解决方案


经过数小时的调试并遇到奇怪的错误,我意识到我的错误比我想象的要简单。错误是:

{"error":true, "reason":"Value of type 'String' required for key 'password'."}

我试图向邮递员发送一个没有返回密钥“密码”的请求:

{"error": true, "reason": "Value required for key 'password'."}

是什么让我分析了我的对象,然后我看到了错误,我的 Create 对象没有正确展开,更准确地说是:

let password: String

应该有一个像这样在字符串旁边。

let password: String!

这在 Postman 而不是 URLSession 上起作用的原因仍不清楚。

更新:

正如@vadian 所提议的,此 URLSession 中的标头也丢失了,即使在我添加强制解包之后,API 也通过了请求,但内容为零

 urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
 urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")

推荐阅读