使用Alamofire发送带有字典数组的放置请求

问题描述 投票:1回答:1

我正在尝试通过以下方式发送JSON put body请求。当我手动输入JSON作为字符串时,它可以工作,但是当我尝试通过代码创建JSON时,它失败:

struct Item: Codable {
    let name: String
    let price: Float
}

struct User: Codable {
    let username: String
    let fullName: String
}

let item = Item(name: "pen", price: 0)
let itemData = try! JSONEncoder().encode(item)
let itemString = String(data: itemData, encoding: .utf8)!

let user = User(username: "Dave", fullName: "Dave Grohl")
let userData = try! JSONEncoder().encode(user)
let userString = String(data: userData, encoding: .utf8)!

let parametersJson: [String: Any] = [
    "item": itemString,
    "user": userString
]

Alamofire请求如下:

AF.request("http://127.0.0.1:8000/items/10",
       method: .put,
       parameters: parametersJson,
       encoding: JSONEncoding.default)
.response { (response) in
    debugPrint(response)

我得到的回应:

[Response Body]: 
{"detail":[{"loc":["body","item"],"msg":"value is not a valid dict","type":"type_error.dict"},{"loc":["body","user"],"msg":"value is not a valid dict","type":"type_error.dict"}]}

同时,当我使用以下参数时,它可以正常工作:

let parameters: [String: [String:String]] = [
"item": [
    "name": "pen",
    "price": "0"
],
"user": [
    "username": "dave",
    "full_name": "Dave Grohl"
]

非常感谢您的帮助。

根据科学怪人的评论,我已经更改了User结构,以更正fullName和full_name之间的不匹配,但仍然会收到相同的错误。当我调试打印请求时,得到以下信息:

[Request Body]: 
{"user":"{\"username\":\"Dave\",\"full_name\":\"Dave Grohl\"}","item":"{\"name\":\"pen\",\"price\":0}"}

这就是使用参数(如上定义为字符串)时得到的:

[Request Body]: 
{"item":{"name":"pen","price":"0"},"user":{"username":"dave","full_name":"Dave Grohl"}}
ios json swift alamofire
1个回答
0
投票

更新:这里的主要问题是您没有正确格式化JSON,这是您需要做的事情:

struct Item: Codable {
    let name: String
    let price: Float
}
struct User: Codable {
    let username: String
    let fullName: String

    enum CodingKeys: String, CodingKey {
        case username
        case fullName = "full_name"
    }
}
struct Parameter: Codable {
    let user: User
    let item: Item
}
let item = Item(name: "pen", price: 0)
let user = User(username: "Dave", fullName: "Dave Grohl")
let parameter = Parameter(user: user, item: item)

let data = try! JSONEncoder().encode(parameter)

var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.httpBody = data
AF.request(request).response { (response) in
    debugPrint(response)
    //...
}

上一个答案:这是因为您的参数在User中不匹配。您可以通过如下修改User结构来修复它:

struct User: Codable {
    let username: String
    let fullName: String

    enum CodingKeys: String, CodingKey {
        case username
        case fullName = "full_name"
    }
}

另一种方法是使用自定义JSONDecoder并将其从keyEncodingStrategy设置为convertToSnakeCase,如下所示:

let user = User(username: "Dave", fullName: "Dave Grohl")
let decoder = JSONEncoder()
decoder.keyEncodingStrategy = .convertToSnakeCase
let userData = try! decoder.encode(user)
let userString = String(data: userData, encoding: .utf8)!

注意:通常JSON格式同时包含蛇形和驼峰形,因此我认为使用第一种方法是更好的选择。但是两者都可以。

© www.soinside.com 2019 - 2024. All rights reserved.