gpt4 book ai didi

ios - 快速将动态服务器响应转换为模型类

转载 作者:行者123 更新时间:2023-12-01 19:29:27 26 4
gpt4 key购买 nike

以下是服务器响应处理父结构...

struct ServerResponse<T: Codable>: Codable {

let status: Bool?
let message: String?
let data: T?

enum CodingKeys: String, CodingKey {
case status = "status"
case message = "message"
case data = "data"
}

init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
status = try values.decodeIfPresent(Bool.self, forKey: .status)
message = try values.decodeIfPresent(String.self, forKey: .message)
data = try values.decodeIfPresent(T.self, forKey: .data)
}
}
AppUserResponse结构:
struct AppUserResponse: Codable  {

let accessToken : String?
let askForMobileNo : Int?
let tokenType : String?
let user : AppUser?

enum CodingKeys: String, CodingKey {
case accessToken = "access_token"
case askForMobileNo = "ask_for_mobile_no"
case tokenType = "token_type"
case user = "user"
}

init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
accessToken = try values.decodeIfPresent(String.self, forKey: .accessToken)
askForMobileNo = try values.decodeIfPresent(Int.self, forKey: .askForMobileNo)
tokenType = try values.decodeIfPresent(String.self, forKey: .tokenType)
user = try values.decodeIfPresent(AppUser.self, forKey: .user)
}

}

struct AppUser: Codable {

let createdAt : String?
let deviceToken : String?
let deviceType : String?
let email : String?
let emailVerifiedAt : String?
let firstName : String?
let id : Int?
let lastName : String?
let mobile_no : String?
let mobileVerified : Int?
let mobileVerifiedAt : String?
let provider : String?
let providerId : String?
let status : Int?
let updatedAt : String?

enum CodingKeys: String, CodingKey {

case createdAt = "created_at"
case deviceToken = "device_token"
case deviceType = "device_type"
case email = "email"
case emailVerifiedAt = "email_verified_at"
case firstName = "first_name"
case id = "id"
case lastName = "last_name"
case mobile_no = "mobile_no"
case mobileVerified = "mobile_verified"
case mobileVerifiedAt = "mobile_verified_at"
case provider = "provider"
case providerId = "provider_id"
case status = "status"
case updatedAt = "updated_at"

}

init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
createdAt = try values.decodeIfPresent(String.self, forKey: .createdAt)
deviceToken = try values.decodeIfPresent(String.self, forKey: .deviceToken)
deviceType = try values.decodeIfPresent(String.self, forKey: .deviceType)
email = try values.decodeIfPresent(String.self, forKey: .email)
emailVerifiedAt = try values.decodeIfPresent(String.self, forKey: .emailVerifiedAt)
firstName = try values.decodeIfPresent(String.self, forKey: .firstName)
id = try values.decodeIfPresent(Int.self, forKey: .id)
lastName = try values.decodeIfPresent(String.self, forKey: .lastName)
mobile_no = try values.decodeIfPresent(String.self, forKey: .mobile_no)
mobileVerified = try values.decodeIfPresent(Int.self, forKey: .mobileVerified)
mobileVerifiedAt = try values.decodeIfPresent(String.self, forKey: .mobileVerifiedAt)
provider = try values.decodeIfPresent(String.self, forKey: .provider)
providerId = try values.decodeIfPresent(String.self, forKey: .providerId)
status = try values.decodeIfPresent(Int.self, forKey: .status)
updatedAt = try values.decodeIfPresent(String.self, forKey: .updatedAt)
}

}
TempUserResponse结构
struct TempUserResponse : Codable {

let askForMobileNo : Int?
let provider : String?
let providerId : String?
let tempUser : TempUser?

enum CodingKeys: String, CodingKey {
case askForMobileNo = "ask_for_mobile_no"
case provider = "provider"
case providerId = "provider_id"
case tempUser = "temp_user"
}

init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
askForMobileNo = try values.decodeIfPresent(Int.self, forKey: .askForMobileNo)
provider = try values.decodeIfPresent(String.self, forKey: .provider)
providerId = try values.decodeIfPresent(String.self, forKey: .providerId)
tempUser = try values.decodeIfPresent(TempUser.self, forKey: .tempUser)
}

}


struct TempUser : Codable {

let email : String?
let name : String?

enum CodingKeys: String, CodingKey {
case email = "email"
case name = "name"
}

init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
email = try values.decodeIfPresent(String.self, forKey: .email)
name = try values.decodeIfPresent(String.self, forKey: .name)
}

}
问题
  • 在应用程序中,我们有 2 个按钮,1. FB 登录和 2. Google 登录
  • 当我尝试使用新用户登录时,服务器返回此响应(此时用户未注册,所以我在“数据”中得到“tempUser”)
        {
    "status": true,
    "message": "User social email address verified, mobile number unverified!.",
    "data": {
    "temp_user": {
    "name": "dhaval solanki",
    "email": "dhaval.sassyinfotech@gmail.com"
    },
    "provider": "google",
    "provider_id": "112620316711299944315",
    "ask_for_mobile_no": 1
    }
    }
  • 当我使用注册用户登录时,我收到以下响应...
      {
    "status": true,
    "message": "User logged in successfully.",
    "data": {
    "user": {
    "id": 60,
    "first_name": "Ankit",
    "last_name": "Joshi",
    "mobile_no": "9876543211"
    },
    "access_token": "eyJLCJhbGciOiJIUzI1NR..",
    "token_type": "bearer",
    "ask_for_mobile_no": 0
    }
    }
  • 使用以下将响应转换为模型类(我使用 Alamofire 进行 api 调用)
      let decoder = JSONDecoder()
    do {

    let responseData = try decoder.decode(ServerResponse <TempUserResponse>.self, from: serverData)
    success(responseData as AnyObject)
    } catch {
    print("Error = \(error)")
    do {
    let responseData = try decoder.decode(ServerResponse<AppUserResponse>.self, from: serverData)
    success(responseData as AnyObject)
    } catch {
    failure(error.localizedDescription as AnyObject)
    }
    }

  • 当我运行此代码时,它总是会尝试将响应转换为 ServerResponse<TempUserResponse>即使响应的类型为 ServerResponse<AppUserResponse> .
    那么如何通过将响应转换为受人尊敬的模型类来管理这两种响应呢?

    最佳答案

    您的 JSON 响应的解码总是在第一次尝试中成功(使用 TempUserResponse 类型),因为您的所有属性都是可选的并且使用 decodeIfPresent<T>(_:forKey:) 解码功能。
    所以,JSONDecoder假设键的值 data在您的根对象中是 TempUserResponse实例,但所有属性都设置为 nil . (JSON 中不存在任何属性键)
    为了避免这种行为,您可以设置一个对您有意义的属性,在 TempUserResponse 中是强制性的。 ,例如 tempUser :

    struct TempUserResponse : Codable {
    let askForMobileNo: Int?
    let provider: String?
    let providerId: String?
    let tempUser: TempUser

    enum CodingKeys: String, CodingKey {
    case askForMobileNo = "ask_for_mobile_no"
    case provider = "provider"
    case providerId = "provider_id"
    case tempUser = "temp_user"
    }

    init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    askForMobileNo = try values.decodeIfPresent(Int.self, forKey: .askForMobileNo)
    provider = try values.decodeIfPresent(String.self, forKey: .provider)
    providerId = try values.decodeIfPresent(String.self, forKey: .providerId)
    tempUser = try values.decode(TempUser.self, forKey: .tempUser)
    }
    }
    如果 tempUser key 存在于 JSON 中,如果不存在则会失败并回退到 AppUserResponse解码。
    更新 :另一种解决方案是将两个结构合并为一个,并将其所有属性作为可选项。
    这样你的模型会简单很多:
    struct UserResponse: Codable  {
    let accessToken: String?
    let askForMobileNo: Int?
    let tokenType: String?
    let user: AppUser?

    let provider: String?
    let providerId: String?
    let tempUser: TempUser?

    enum CodingKeys: String, CodingKey {
    case accessToken = "access_token"
    case askForMobileNo = "ask_for_mobile_no"
    case tokenType = "token_type"
    case user = "user"

    case provider = "provider"
    case providerId = "provider_id"
    case tempUser = "temp_user"
    }

    init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    accessToken = try values.decodeIfPresent(String.self, forKey: .accessToken)
    askForMobileNo = try values.decodeIfPresent(Int.self, forKey: .askForMobileNo)
    tokenType = try values.decodeIfPresent(String.self, forKey: .tokenType)
    user = try values.decodeIfPresent(AppUser.self, forKey: .user)

    provider = try values.decodeIfPresent(String.self, forKey: .provider)
    providerId = try values.decodeIfPresent(String.self, forKey: .providerId)
    tempUser = try values.decodeIfPresent(TempUser.self, forKey: .tempUser)
    }
    }
    注意:不包括未更改的结构。
    解码代码将如下所示:
    let decoder = JSONDecoder()
    do {
    let responseData = try decoder.decode(ServerResponse<UserResponse>.self, from: Data(jsonString.utf8))
    print(responseData)
    } catch {
    print(error)
    }
    你可以检查一下 usertempUser属性(property)存在以确定您的情况。

    关于ios - 快速将动态服务器响应转换为模型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63938603/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com