【问题标题】:How to parse JSON to nested struct in Swift?如何在 Swift 中将 JSON 解析为嵌套结构?
【发布时间】:2018-10-04 16:24:18
【问题描述】:

我要解析这个 JSON:

{
    "status": 1,
    "member": {
        "id": "3",
        "member_no": "1111",
        "username": "uname",
        "name": "name",
        "email": "user@name.com",
        "phone": "123 123",
        "point": "100",
        "expiry": "2019-09-22",
        "grade": {
            "id": "2",
            "name": "Member"
        }
    }
}

我创建了这个结构:

struct User: Codable {
    var status: Int?
    var member: Member?
    var msg: String?

    struct Member: Codable {
        var id: Int?
        var member_no: String?
        var username: String?
        var name: String?
        var email: String?
        var phone: String?
        var point: String?
        var expiry: String?
        var grade: Grade?

        struct Grade: Codable {
            var id: Int?
            var name: String?
        }
    }
}

并用它来解码:

let decoder = JSONDecoder()
let user = try decoder.decode(User.self, from: data)

但是我收到了这个错误:

无法读取数据,因为它的格式不正确。

如果struct只有一层也没问题:

struct User: Codable {
    var status: Int?
    var msg: String?
}

如何编写一个结构来匹配这个 JSON?

【问题讨论】:

  • id 不是整数。
  • 它可以是 Int 取决于响应。我们可以迅速采取任何我们想要的方式
  • @AdityaSharma 不,它不能。看看 JSON。这是一个字符串。它不会因为您将属性键入为 Int 而神奇地变成 Int。
  • 哦,对不起
  • 以后解析 JSON 时不再使用print(error.localizedDescription),始终使用print(error)。它会向您显示实际错误 Expected to decode Int but found a string/data instead 以及受影响的 CodingKey 而不是更通用和误导性 无法读取数据...

标签: json swift codable


【解决方案1】:

您可能想尝试以下方法,这对我来说似乎很好。

首先我们需要为我们的结构User创建CodingKeys

使用 codable 时,即使成员内部的 MemberGrade 相互嵌套。您应该在 User 结构中声明这些结构。

正如您在下面看到的那样,成员和等级应该符合Codable,而用户在扩展中符合Decodable,并通过将其用作容器来使用解码器进行初始化。

此外,由于在您的 json 文件中,您在用户和等级中都有 idString,但在您的代码中您将它们声明为 Int,所以我也修复了它们。

下面的代码实现了我上面提到的structs和CodingKeys,试着像我一样接近或者复制粘贴试试,应该没问题:

带有 CodingKeys 的用户结构:

struct User {
var status: Int?
var member: Member?

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

成员和等级结构:

struct Member: Codable {
var id: String?
var member_no: String?
var username: String?
var name: String?
var email: String?
var phone: String?
var point: String?
var expiry: String?
var grade: Grade?
}

struct Grade: Codable {
var id: String?
var name: String?
}

用户扩展以符合 Codable:

extension User: Decodable {
init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    self.status = try container.decode(Int?.self, forKey: .status)
    self.member = try container.decode(Member?.self, forKey: .member)
}
}

现在创建一个解码器并尝试如下解码:

    let decoder = JSONDecoder()
    let user = try! decoder.decode(User.self, from: data)

我希望这对您有所帮助并正常工作

【讨论】:

    【解决方案2】:

    xcode 可能给你一个错误,说你的结构不符合可解码协议,你不在乎:]

    这是你的结构(模型)应该是什么样子

    
    struct User: Codable {
        let status: Int?
        let member: Member?
    }
    
    

    struct Member: Codable { let id, memberNo, username, name: String? let email, phone, point, expiry: String? let grade: Grade?

    enum CodingKeys: String, CodingKey {
        case id
        case memberNo = "member_no"
        case username, name, email, phone, point, expiry, grade
    }
    

    }

    struct Grade: Codable { let id, name: String? }

    【讨论】:

      【解决方案3】:

      试试这个

      import Foundation
      
      struct User: Codable {
          let status: Int
          let member: Member
      }
      
      struct Member: Codable {
          let id, memberNo, username, name: String
          let email, phone, point, expiry: String
          let grade: Grade
      
          enum CodingKeys: String, CodingKey {
              case id
              case memberNo = "member_no"
              case username, name, email, phone, point, expiry, grade
          }
      }
      
      struct Grade: Codable {
          let id, name: String
      }
      

      【讨论】:

        【解决方案4】:

        结构用户:可编码{ 变量状态:整数? var 成员:成员? var msg: 字符串?

        struct Member: Codable {
            var id: String?
            var member_no: String?
            var username: String?
            var name: String?
            var email: String?
            var phone: String?
            var point: String?
            var expiry: String?
            var grade: Grade?
        
            struct Grade: Codable {
                var id: String?
                var name: String?
            }
        }
        

        }

        【讨论】:

          【解决方案5】:

          id 中有字符串而不是整数:

          struct User: Codable {
              var status: Int?
              var member: Member?
          
              struct Member: Codable {
                  var id: String?
                  var member_no: String?
                  var username: String?
                  var name: String?
                  var email: String?
                  var phone: String?
                  var point: String?
                  var expiry: String?
                  var grade: Grade?
          
                  struct Grade: Codable {
                      var id: String?
                      var name: String?
                  }
              }
          }
          
          let decoder = JSONDecoder()
          do {
              let user = try decoder.decode(User.self, from: data)
          } catch {
              print(error)
          }
          

          【讨论】:

            猜你喜欢
            • 2020-11-29
            • 2016-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-15
            • 2018-04-10
            • 1970-01-01
            • 2018-12-01
            相关资源
            最近更新 更多