如何在swift中将JSON转换为结构类型数据?

如何在swift中将JSON转换为结构类型数据?,json,swift,json-deserialization,Json,Swift,Json Deserialization,我有一个API供我的用户登录到数据库。我使用以下代码将凭据发送到API,如果它们有效,我将获取一些关于用户信息的JSON类型的数据。否则我会得到一个字符串,表明用户名或密码是错误的。 以下是我的HTTTP Post请求: let url = URL(string: "http://128.199.199.17:3000/api/login")! var request = URLRequest(url: url) request.setValue("applica

我有一个API供我的用户登录到数据库。我使用以下代码将凭据发送到API,如果它们有效,我将获取一些关于用户信息的JSON类型的数据。否则我会得到一个字符串,表明用户名或密码是错误的。 以下是我的HTTTP Post请求:

let url = URL(string: "http://128.199.199.17:3000/api/login")!
        var request = URLRequest(url: url)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        let postString = "email=22222@gmail.com&password=123456"
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) { data, response, error in


            guard let data = data, error == nil else {
                print("error=\(String(describing: error))")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("\(String(describing: response))")
            }

            let responseString = String(data: data, encoding: .utf8)
            print("responseString = \(responseString!)")
        }
        task.resume()
它工作正常,我在控制台中获得以下信息:

{
  "user_id": 2,
  "email": "22222@gmail.com",
  "password": "123456",
  "user_name": "number 2 name",
  "full_name": "danial kosarifar",
  "sex": "male",
  "height": 0,
  "weight": 0,
  "number_of_meal_per_day": 3,
  "water_amount": 0,
  "calories": 0,
  "number_of_hours_to_sleep_per_day": 3,
  "createdAt": "2017-11-14T17:23:31.000Z",
  "updatedAt": "2017-11-14T17:25:37.000Z"
}
我还创建了一个可解码结构,如下所示:

struct User : Decodable {

let user_id : Int
let email : String
let password : String
let username : String 
} 
我的问题不是将数据解码成字符串,而是如何将它们解码成我定义的结构。我对这个话题是完全陌生的,如果我的问题对初学者来说太多了,请容忍我。
谢谢你,斯威夫特4:

最好将
struct
创建为
Codable
如下所示

struct User:Codable { //Because enum CodingKeys: String, CodingKey {

    let userID : Int
    let email : String
    let password : String
    let userName : String
    let fullName:String
    let sex:String
    let height:Int
    let weight:Int
    let numberOfMealPerDay:Int
    let waterAmount:Int
    let calories:Int
    let numberOfHoursToSleppPerDay:Int
    let createdAt:String
    let updatedAt:String

    enum CodingKeys: String, CodingKey {
        case userID = "user_id"
        case email
        case password
        case userName = "user_name"
        case fullName = "full_name"
        case sex
        case height
        case weight
        case numberOfMealPerDay = "number_of_meal_per_day"
        case waterAmount = "water_amount"
        case calories
        case numberOfHoursToSleppPerDay = "number_of_hours_to_sleep_per_day"
        case createdAt
        case updatedAt
    }
}
使用
JSONDecoder

然后,可以使用
jsondeconder
解析
closure
任务中的响应数据
data
。这里,
user
class
变量。i、 例如,
var用户:用户?

if let json = try? JSONDecoder().decode(User.self, from: data!){

    self.user = json
}

注意:为了更好地理解,这是我关于swift 4中JSON解析的系列文章

您可以向用户结构添加一个自定义初始值设定项,该初始值设定项将JSON数据作为参数并使其抛出。您还需要创建一个自定义日期格式化程序来解析您的日期(您需要在其中包含毫秒)。请注意,如果json响应可能不包含某些键/值,则需要将该属性设置为可选:

因此,对于日期格式化程序,您可以从以下位置使用此自定义日期格式化程序:


您的用户结构应如下所示:

struct User: Codable {
    let id: Int
    let email: String
    let password: String
    let userName: String
    let fullName: String
    let sex: String
    let height: Int
    let weight: Int
    let mealsPerDay: Int
    let waterAmount: Int
    let calories: Int
    let hoursToSleepPerDay: Int
    let createdAt: Date
    let updatedAt: Date
    // you can provide different keys to your user struct properties
    private enum CodingKeys: String, CodingKey {
        case id = "user_id", email, password, userName = "user_name", fullName = "full_name", sex, height, weight, mealsPerDay = "number_of_meal_per_day", waterAmount = "water_amount", calories, hoursToSleepPerDay = "number_of_hours_to_sleep_per_day", createdAt, updatedAt
    }
    // custom initializer that takes the json data and throws in case of error
    init(data: Data) throws {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .formatted(Formatter.iso8601)
        self = try decoder.decode(User.self, from: data)
    }
}

用法:

let data = Data("""
{
  "user_id": 2,
  "email": "22222@gmail.com",
  "password": "123456",
  "user_name": "number 2 name",
  "full_name": "danial kosarifar",
  "sex": "male",
  "height": 0,
  "weight": 0,
  "number_of_meal_per_day": 3,
  "water_amount": 0,
  "calories": 0,
  "number_of_hours_to_sleep_per_day": 3,
  "createdAt": "2017-11-14T17:23:31.000Z",
  "updatedAt": "2017-11-14T17:25:37.000Z"
}
""".utf8)

do {
    let user = try User(data: data)
    print(user)  // User(id: 2, email: "22222@gmail.com", password: "123456", userName: "number 2 name", fullName: "danial kosarifar", sex: "male", height: 0, weight: 0, mealsPerDay: 3, waterAmount: 0, calories: 0, hoursToSleepPerDay: 3, createdAt: 2017-11-14 17:23:31 +0000, updatedAt: 2017-11-14 17:25:37 +0000)\n"
} catch {
    print(error)
}
let data = Data("""
{
  "user_id": 2,
  "email": "22222@gmail.com",
  "password": "123456",
  "user_name": "number 2 name",
  "full_name": "danial kosarifar",
  "sex": "male",
  "height": 0,
  "weight": 0,
  "number_of_meal_per_day": 3,
  "water_amount": 0,
  "calories": 0,
  "number_of_hours_to_sleep_per_day": 3,
  "createdAt": "2017-11-14T17:23:31.000Z",
  "updatedAt": "2017-11-14T17:25:37.000Z"
}
""".utf8)

do {
    let user = try User(data: data)
    print(user)  // User(id: 2, email: "22222@gmail.com", password: "123456", userName: "number 2 name", fullName: "danial kosarifar", sex: "male", height: 0, weight: 0, mealsPerDay: 3, waterAmount: 0, calories: 0, hoursToSleepPerDay: 3, createdAt: 2017-11-14 17:23:31 +0000, updatedAt: 2017-11-14 17:25:37 +0000)\n"
} catch {
    print(error)
}