如果字典为空,则可编码问题

Posted

技术标签:

【中文标题】如果字典为空,则可编码问题【英文标题】:Codable Issue If Dictionary is Empty 【发布时间】:2019-02-15 11:22:28 【问题描述】:

我正在尝试快速使用 Codable 协议 问题是我需要从服务器获取嵌套字典。认为 数据:它的值和内部数据的另一个字典目标 如果数据中的目标有一个值,它可以正常工作 但是如果字典里面的目标是空的,它会说 错误 - 由于格式不正确,无法读取数据。

我的 JSON 响应 案例 1 - 没有目标 - 面临的问题


  "code": "1",
  "message": "Data fetched successfully",
  "data": 
    "id": "2",
    "organization_id": "2",
    "first_name": "ios",
    "last_name": "test",
    "user_name": "iOS",
    "email": "ios@gmail.com",
    "password": "4399578cc31cf62535a7dba566e4aea0",
    "security_hash": "fdf4d3bb5731de23b42771e01d9e0c3e",
    "google_id": "525256562",
    "facebook_id": "525256562",
    "access_code": "iosTest1",
    "gender": "",
    "contact": "1234567890",
    "user_profile": "",
    "profile_thumb": "",
    "dob": "",
    "weight": "",
    "height": "",
    "is_corporate": "0",
    "status": "1",
    "created_at": "2018-04-19 10:37:46",
    "updated_at": "2018-12-10 15:32:59",
    "profile_image_url": "",
    "goal": 
  

案例 2:当 Goal 有值时


  "code": "1",
  "message": "Data fetched successfully",
  "data": 
    "id": "2",
    "organization_id": "2",
    "first_name": "iOS",
    "last_name": "test",
    "user_name": "ios",
    "email": "ios@gmail.com",
    "password": "4399578cc31cf62535a7dba566e4aea0",
    "security_hash": "fdf4d3bb5731de23b42771e01d9e0c3e",
    "google_id": "525256562",
    "facebook_id": "525256562",
    "access_code": "iosTest1",
    "gender": "",
    "contact": "1234567890",
    "user_profile": "",
    "profile_thumb": "",
    "dob": "",
    "weight": "",
    "height": "",
    "is_corporate": "0",
    "status": "1",
    "created_at": "2018-04-19 10:37:46",
    "updated_at": "2018-12-10 15:32:59",
    "profile_image_url": "",
    "goal": 
      "id": "4",
      "client_id": "2",
      "ambition_to_achieve": "adfadf",
      "current_assessment": "dfadfafa",
      "expected": "fasdfasdfsafsf",
      "expected_date": "2018-12-15",
      "description": "asdfadsfadf",
      "goal_status": "1",
      "created_at": "2018-12-12 18:15:36",
      "updated_at": ""
    
  

///--- 处理主要数据的主类

struct LoggedUser: Codable 
    var dob, weight, height: String?
    let accesscode, contact, contactcode, email, facebookid: String?
    let firstname, gender, googleid, id, iscorporate, lastname: String?
    let organizationid, password, profilethumb, securityhash, status: String?
    let username, userprofile : String?
    let goal:Goal?

    enum CodingKeys: String, CodingKey 
        case accesscode="access_code"
        case contact, dob, email, gender, height, id, password, status, weight, goal
        case contactcode="contact_code"
        case facebookid="facebook_id"
        case firstname="first_name"
        case googleid="google_id"
        case iscorporate="is_corporate"
        case lastname="last_name"
        case organizationid="organization_id"
        case profilethumb="profile_thumb"
        case securityhash="security_hash"
        case username="user_name"
        case userprofile="user_profile"
    

/// ---> 目标分类

struct Goal: Codable 
    let id, clientID, ambitionToAchieve, currentAssessment: String?
    let expected, expectedDate, description, goalStatus: String?
    let createdAt, updatedAt: String?

    enum CodingKeys: String, CodingKey 
        case id
        case clientID = "client_id"
        case ambitionToAchieve = "ambition_to_achieve"
        case currentAssessment = "current_assessment"
        case expected
        case expectedDate = "expected_date"
        case description
        case goalStatus = "goal_status"
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    

----> 更新 只是更正 发表实际回应

Get My Goal API Response ==> ["code": 1, "message": Data fetched successfully, "data": 
    "access_code" = iosTest4;
    contact = 1111111111;
    "contact_code" = 91;
    "created_at" = "2019-02-12 14:42:34";
    dob = "1996-05-10";
    email = "testing@email.com";
    "facebook_id" = "";
    "first_name" = iOS;
    gender = 1;
    goal =     (
    );
    "google_id" = "";
    height = "5.10";
    id = 35;
    "is_corporate" = 0;
    "last_name" = test;
    "organization_id" = 0;
    password = 915729f1e48bda300dabaac7d1ac8358;
    "profile_image_url" = "";
    "profile_thumb" = "";
    "security_hash" = 991f5cd86be6fc485633d1946dc84a7a;
    status = 1;
    "updated_at" = "2019-02-14 16:25:01";
    "user_name" = "testing@email.com";
    "user_profile" = "";
    weight = "0.10";
]

【问题讨论】:

从不 print(error.localizedDescription) 捕获 Decodable 错误时。始终打印 error 实例。您会收到一条非常全面的消息,详细描述了错误。 无法读取数据,因为它的格式不正确。这就是打印出来的 真的吗?即使你print(error) Error ==> typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "goal", intValue: nil)], debugDescription: “应解码 Dictionary 但找到了一个数组。”,underlyingError: nil)) 正如我所说,错误信息很清楚。 goal 是一个数组,不是字典。 【参考方案1】:

当我得到 2 种不同的格式时 当目标为空时,它给了我一个数组 当有一些值时,它返回一个字典 所以我通过手动将目标转换为 [String:Any] 来显式创建自己的 Data()

var loginDataDict = jsonDict["data"] as! [String:Any]
if let goalData = loginDataDict["goal"] as? [String:Any] 
   loginDataDict.updateValue(goalData, forKey: "goal")
 else 
   loginDataDict.updateValue([:], forKey: "goal")
 

这可能不是一个合适的解决方案,但如果与我在这里遇到的情况相同,可能会对某人有所帮助

【讨论】:

以上是关于如果字典为空,则可编码问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在“可编码”响应中使用字典?

Swift:如何将可编码类型作为函数输入传递给编码或解码 json

将可编码结构编码为 Alamofire POST 参数 - Swift

JS:如果沿嵌套字典路径为空,则返回默认值[重复]

如何在可编码结构中使用计算属性(swift)

使 NSDecimalNumber 可编码