【问题标题】:Parsing JSON response using Codable in Swift在 Swift 中使用 Codable 解析 JSON 响应
【发布时间】:2020-01-14 00:40:10
【问题描述】:

我将收到一个带有对象数组的 JSON 格式的 API 响应。例如,

{
        "Header": "Verification",
        "Info": [
            {
                "mobile": "**** **** 123"
            },
            {
                "email": "s******k**@g***.com"
            }
        ],
}

我使用了 Codable 功能并创建了一个如下所示的结构,

struct cResponse: Codable 
{
  var Header: String?
  var Info: [Info] 
}

struct Info: Codable {
  var mobile: String!
  var email: String!
}

我正在尝试使用 JSONDecoder 快速解码 JSON 响应,如下面的代码,

let decoder = JSONDecoder()
let decodedcRES: cResponse = try decoder.decode(cResponse.self, from: CData)

在来自服务器的信息仅是移动设备和电子邮件之前,这一切正常。

但 Info 在运行时将是动态的(即)我将在 Info 下从服务器接收更多 JSON 对象。因此,如果我创建一个如下所示的结构,

struct cResponse: Codable 
{
  var Header: String?
  var Info: [String] 
}

我收到“无法读取数据,因为它的格式不正确。”作为错误。

如何使用 Codable 功能快速处理动态 JSON 数组对象?

【问题讨论】:

  • Info 是对象数组,不是字符串数组
  • 而不是error.localizedDescription 打印error 实例。它准确地告诉你出了什么问题。并且永远永远不会在将使用Decodable 解码的结构中声明成员作为隐式展开可选。并且名称属性和变量总是小写以避免潜在的命名空间冲突

标签: ios json swift


【解决方案1】:

Info 是对象数组,所以你可以做这样的事情来解析它。

struct cResponse: Codable 
{
  var Header: String?
  var Info: [[String : String]] 
}

【讨论】:

  • 您忘记实现CodingKeys enum & init(decoder: Decoder) 来解析mobile/email 值。
【解决方案2】:

信息键包含对象数组,因此将结构更改为:

struct cResponse: Codable
{
    var Header: String?
    var Info: [[String: String]]
}

【讨论】:

  • 感谢您的回复。以前我使用 [String : Any] 作为信息。现在我使用 [String: String] 并且效果很好。
  • @user7413163 Any默认不符合codable协议,所以需要实现encode和decode方法。
【解决方案3】:

更好的方法是使用自定义枚举作为可解码对象:

enum ContactType: Decodable {
    case email(String)
    case mobile(String)
    case unknown
    enum MyKeys: String, CodingKey {
        case email
        case mobile
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: MyKeys.self)
        if let emailString = try? container.decode(String.self, forKey: .email) {
            self = .email(emailString)
        } else if let mobileString = try? container.decode(String.self, forKey: .mobile) {
            self = .mobile(mobileString)
        } else {
            self = .unknown
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    相关资源
    最近更新 更多