在Swift模型中解码数组(可解码)

时间:2018-12-23 20:34:14

标签: arrays swift decodable encodable

我正在从API检索JSON,我想为我使用的每个端点创建一个模型。

所有端点都使用以下格式:

{
  "id": "xxxxxx",
  "result": {…},
  "error": null
}

关键是:

  • id始终是字符串
  • error可以为 null 或包含键的对象
  • result可以为 null ;对象或数组。

我遇到的问题是,在端点之一上,结果是数组数组:

{
  "id": "xxxxxx",
  "result": [
      [
          "client_id",
          "name",
          50,
          "status"
      ]
  ],
  "error": null
}

如您所见,我有一个数组数组,其中值可以是String或Int。

如何使用Decodable协议对此进行解码,然后根据其原始值将这些解码后的值用作String或Int?

1 个答案:

答案 0 :(得分:1)

categories

改善了@ArinDavoodian的答案。

要读取数据:

import Foundation

let string =  """
{
"id": "xxxxxx",
"result": [
[
"client_id",
"name",
50,
"status"
]
],
"error": null
}
"""

struct Container: Codable {
    let id: String
    let result: [[Result]]
    let error: String?
}

enum Result: Codable {
    case integer(Int)
    case string(String)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(Int.self) {
            self = .integer(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        throw DecodingError.typeMismatch(Result.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Result"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(self)
    }
}

let jsonData = string.data(using: .utf8)!
let container = try? JSONDecoder().decode(Container.self, from: jsonData)

print(container)

一个简单的解决方案:

container?.result.first?.forEach { object in
    switch object {
    case let .integer(intValue):
        print(intValue)
        break
    case let .string(stringValue):
        print(stringValue)
        break
    }
}