如何将 URLSession 中嵌套的原始 JSON 发送到 Vapor API?

How to send nested raw JSON in URLSession to 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 抛出解码错误:

解码错误:键 'password' 需要类型 'String' 的值。

起初我以为问题出在 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\":\"\",\"countryCode\":,\"nationalNumber\":}}"

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,还是我需要更改我的逻辑以便它接收平面数组?

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

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

然后我尝试向 Postman 发送一个没有返回密钥 'password' 的请求:

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

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

let password: String

应该像这样在 String 旁边有一个 !

let password: String!

这对 Postman 而对 URLSession 不起作用的原因仍不清楚。

更新:

正如@vadian 所建议的那样,此 URLSession 中的 headers 也丢失了,甚至在我添加力解包后 API 也通过了请求,但内容为零

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

同时设置 content-type 和长度 header

 urlRequest.setValue(String(Data(json.utf8).count), forHTTPHeaderField:"Content-Length")
 urlRequest.setValue("application/json", forHTTPHeaderField:"Accept")
 urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")

永远,永远,永远不要将 class 中的属性声明为隐式解包可选,这些属性用 non-optional 值初始化。