如何使用 URLSession post 此 JSON 数据作为 HTTP 正文?

How to post this JSON data as HTTP body using URLSession?

JSON我要post:

{
  "quizId": 1,
  "quizQuestionBanks": [
    {
      "quizQuestionBankId": 4,
      "question": "string",
      "option1": "string",
      "option2": "string",
      "option3": "string",
      "option4": "string",
      "answer": "Guy de Maupassant",
      "explanation": "string"
    }
  ]
}

我做了 URLSession Post 部分。但是不知道如何post这种JSON。早些时候我已经 posted JSON 像这样。

let json: [String: Any] = ["key": "value"]

但这对我来说有点复杂。

下面给出了我为 posting 编写的代码

let url = URL(string: postUrl)! //PUT Your URL

        var request = URLRequest(url: url)

        request.httpMethod = "POST"

        request.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")

        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        request.addValue("Token \(String(describing: token))", forHTTPHeaderField: "Authorization")


        // insert json data to the request
        request.httpBody = jsonData

        URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }
            let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
            if let responseJSON = responseJSON as? [String: Any] {
                print(responseJSON) //Code after Successfull POST Request
            }
        }.resume()

JSONSerialization:

let params: [String: Any] = ["quizId": 1,
                             "quizQuestionBanks": [["quizQuestionBankId": 4,
                                                    "question": "string",
                                                    "option1": "string",
                                                    "option2": "string",
                                                    "option3": "string",
                                                    "option4": "string",
                                                    "answer": "Guy de Maupassant",
                                                    "explanation": "string"]]]

let jsonData = try? JSONSerialization.data(withJSONObject: params)

但是,由于 Swift 4,我们可以使用 Codable:

struct Quiz: Codable {
    let id: Int
    let questions: [Question]

    enum CodingKeys: String, CodingKey {
        case id = "quizId"
        case questions = "quizQuestionBanks"
    }
}

struct Question: Codable {
    let id: Int
    let question: String
    let option1: String
    let option2: String
    let option3: String
    let option4: String
    let answer: String
    let explanation: String

    enum CodingKeys: String, CodingKey {
        case id = "quizQuestionBankId"
        case question
        case option1
        case option2
        case option3
        case option4
        case answer
        case explanation
    }
}

let questions = [Question(id: 4, question: "string", option1: "string", option2: "string", option3: "string", option4: "string", answer: "Guy de Maupassant", explanation: "string")]
let quiz = Quiz(id: 1, questions: questions)
let jsonData = try JSONEncoder().encode(quiz)

option1option2option3option4 可以是结构中的数组(需要自定义 encoding/decoding)。

准备 JSON 数据上传

 struct Quiz: Codable {
        let quizId: Int
        let quizQuestionBanks: [QuizQuestionBank]
    }

struct QuizQuestionBank: Codable {
    let quizQuestionBankId: Int
    let question: String
    let option1: String
    let option2: String
    let option3: String
    let option4: String
    let answer: String
    let explanation: String

}

let quiz = Quiz(quizId: 1, quizQuestionBanks: [QuizQuestionBank(quizQuestionBankId: 4, question: "string", option1: "string", option2: "string", option3: "string", option4: "string", answer: "Guy de Maupassant", explanation: "string")])

guard let uploadData = try? JSONEncoder().encode(quiz) else {
    return
}

配置URL请求

let url = URL(string: "https://example.com/post")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

使用上传任务

let task = URLSession.shared.uploadTask(with: request, from: uploadData) { data, response, error in
        if let error = error {
            print ("error: \(error)")
            return
        }
        guard let response = response as? HTTPURLResponse,
            (200...299).contains(response.statusCode) else {
            print ("server error")
            return
        }
        if let mimeType = response.mimeType,
            mimeType == "application/json",
            let data = data,
            let dataString = String(data: data, encoding: .utf8) {
            print ("got data: \(dataString)")
        }
    }
    task.resume()

请参阅 Apple 开发者网站 中的 link 了解更多详细信息。 https://developer.apple.com/documentation/foundation/url_loading_system/uploading_data_to_a_website