Я знаю, что это не отвечает на вопрос буквально, но это нативное решение с использованием Decodable
.
Декодирует массив для ключа data
в перечисление со связанными значениями.Это обрабатывает различные типы очень гладко.
В перечислении cardTypeId
сначала декодируется, а в переключателе cardInfo
декодируется в зависимости от идентификатора типа в соответствующую структуру.
struct Response : Decodable {
let code : Int
let status : String
let data : [CardData]
}
enum CardData {
case user(UserData), image(ImageData), unknown
}
extension CardData: Decodable {
private enum CodingKeys: String, CodingKey {
case cardTypeId
case cardInfo
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(Int.self, forKey: .cardTypeId)
switch type {
case 1:
let info = try container.decode(UserData.self, forKey: .cardInfo)
self = .user(info)
case 4:
let info = try container.decode(ImageData.self, forKey: .cardInfo)
self = .image(info)
default:
self = .unknown
}
}
}
struct UserData : Decodable {
let text, userName, background : String
let media : Media
}
struct ImageData : Decodable {
let text : String
let media : Media
}
struct Media : Decodable {
let mediaUrl, mediaType, mediaThumbUrl : String
}
let jsonString = """
{
"code": 200,
"status": "success",
"data": [
{
"cardTypeId": 1,
"cardInfo": {
"background": "#4267b2",
"userName": "abkur_rt",
"text": "Hello Video",
"media": {
"mediaUrl": "",
"mediaType": "image",
"mediaThumbUrl": ""
}
}
},
{
"cardTypeId": 4,
"cardInfo": {
"text": "Image and text",
"media": {
"mediaUrl": "",
"mediaType": "image",
"mediaThumbUrl": ""
}
}
}
]
}
"""
let data = Data(jsonString.utf8)
do {
let result = try JSONDecoder().decode(Response.self, from: data)
let cardData = result.data
for item in cardData {
switch item {
case .user(let userData) : print(userData)
case .image(let imageData) : print(imageData)
case .unknown: print("unknown")
}
}
} catch {
print(error)
}