如何从 alamofire 响应中获取任何类型的数组字段?

How to get any type array field from alamofire response?

我的 json 回复中有这样的字段:

"title": [2402, "Dr.", "Prof.", "Prof. Dr.", "HM"]

我想解析它。我有我的模型 class:

struct AppDataModel:Decodable {
    ...
    let title = Dictionary<String,Any>()
    
    
    enum CodingKeys: String,CodingKey{
        case title
        ...
    }
    ...
}

如您所见,我尝试使用 Dictionary<String,Any>()。而且我还考虑过 Any -> [Any] 的数组,但我通常会遇到这样的错误:

Type 'AppDataModel' does not conform to protocol 'Decodable'

我想我必须像普通人一样处理它json。但是我没有在Swift中找到这样的数据类型,只有字典。那么,也许有人知道如何处理这样的响应字段?

这是一个将单个键解码为异构数组的示例

let jsonString = """
{"title": [2402, "Dr.", "Prof.", "Prof. Dr.", "HM"], "name":"Foo"}
"""

struct AppDataModel : Decodable {
    let titles : [String]
    let name : String
    
    private enum CodingKeys: String, CodingKey { case title, name }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        var titlesContainer = try container.nestedUnkeyedContainer(forKey: .title)
        var titleArray = [String]()
        let _ = try titlesContainer.decode(Int.self) // decode and drop the leading integer
        while !titlesContainer.isAtEnd { // decode all following strings
            titleArray.append(try titlesContainer.decode(String.self))
        }
        titles = titleArray
        self.name = try container.decode(String.self, forKey: .name)
    }
}

let data = Data(jsonString.utf8)

do {
    let result = try JSONDecoder().decode(AppDataModel.self, from: data)
    print(result)
} catch {
    print(error)
}
struct AppDataModel: Codable {
    let title: [Title]?
}

extension AppDataModel {
    init(data: Data) throws {
        self = try newJSONDecoder().decode(AppDataModel.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }

    init(fromURL url: URL) throws {
        try self.init(data: try Data(contentsOf: url))
    }

    func with(
        title: [Title]?? = nil
    ) -> AppDataModel {
        return AppDataModel(
            title: title ?? self.title
        )
    }

    func jsonData() throws -> Data {
        return try newJSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

enum Title: 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(Title.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Title"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .integer(let x):
            try container.encode(x)
        case .string(let x):
            try container.encode(x)
        }
    }
}

func newJSONDecoder() -> JSONDecoder {
    let decoder = JSONDecoder()
    if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
        decoder.dateDecodingStrategy = .iso8601
    }
    return decoder
}

func newJSONEncoder() -> JSONEncoder {
    let encoder = JSONEncoder()
    if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
        encoder.dateEncodingStrategy = .iso8601
    }
    return encoder
}

//use

do {
    let appDataModel = try AppDataModel(json)
}
catch{
    //handle error
}