我有一个JSON
{
"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": ""
}
}
}
]
}
要解析这个我使用的ObjectMapper(https://github.com/tristanhimmelman/ObjectMapper)我的查询是在我的JSON中我得到cardInfo
取决于cardTypeId
所以我做了类引用此链接ObjectMapper how to map different object based on JSON以了解如何使用自定义TransformType类。在链接的JSON响应中有Array,但在我的情况下,如果cardTypeId
为1,那么在cardInfo
中有两个额外的字段相同。所以我已经创建了如下所示的类,但我不确定如何创建继承TransFormType的类。
class LBDetailsList: Mappable {
var lbListArray : [LBDetail]?
required init?(map: Map) {
}
func mapping(map: Map) {
lbListArray <- map ["data"]
}
}
class LBDetail: Mappable {
var cardTypeID : Int?
var cardInfo: LBBaseCardInfo?
required init?(map: Map) {
}
func mapping(map: Map)
{
cardInfo <- map["cardInfo"]
}
}
class LBBaseCardInfo: Mappable {
var text: String?
var media: LBMedia?
required init?(map: Map) {
}
func mapping(map: Map) {
text <- map["text"]
media <- map["media"]
}
}
class CardType1: LBBaseCardInfo {
var background, userName : String?
required init?(map: Map) {
super.init(map: map)
}
override func mapping(map: Map) {
super.mapping(map: map)
background <- map["background"]
userName <- map["userName"]
}
}
class CardType2: LBBaseCardInfo {
required init?(map: Map) {
super.init(map: map)
}
override func mapping(map: Map) {
super.mapping(map: map)
}
}
class LBMedia: Mappable {
var mediaURL: String?
var mediaType: String?
var mediaThumbURL: String?
required init?(map: Map) {
}
func mapping(map: Map) {
mediaURL <- map["mediaUrl"]
mediaType <- map["mediaType"]
mediaThumbURL <- map["mediaThumbUrl"]
}
}
请帮助我理解这个框架。
您需要以下列方式创建。
1)BaseClass:
struct BaseClass : Mappable {
var code : Int?
var status : String?
var data : [CardData]?
init?(map: Map) {
}
mutating func mapping(map: Map) {
code <- map["code"]
status <- map["status"]
data <- map["data"]
}
}
2)CardData:
struct CardData : Mappable {
var cardTypeId : Int?
var cardInfo : CardInfo?
init?(map: Map) {
}
mutating func mapping(map: Map) {
cardTypeId <- map["cardTypeId"]
cardInfo <- map["cardInfo"]
}
}
3)媒体:
struct Media : Mappable {
var mediaUrl : String?
var mediaType : String?
var mediaThumbUrl : String?
init?(map: Map) {
}
mutating func mapping(map: Map) {
mediaUrl <- map["mediaUrl"]
mediaType <- map["mediaType"]
mediaThumbUrl <- map["mediaThumbUrl"]
}
}
4)CardInfo:
struct CardInfo : Mappable {
var background : String?
var userName : String?
var text : String?
var media : Media?
init?(map: Map) {
}
mutating func mapping(map: Map) {
background <- map["background"]
userName <- map["userName"]
text <- map["text"]
media <- map["media"]
}
}
我已经根据你的json创建了以下Mappable结构。如果你的json没有包含任何键,那么它将用nil值解析json。
对于你的CardInfo
,我设置了var text : String?
,这意味着,如果没有这个键,json将使用nil进行解析。所以当你使用它时,你必须在打开之前检查不是nil。
我希望这能帮到您。
我知道它不会从字面上回答这个问题,但这是使用Decodable
的原生解决方案。
它将关键data
的数组解码为具有关联值的枚举。这非常顺利地处理不同的类型。
在枚举中,cardTypeId
首先被解码,并且在开关中,cardInfo
根据类型ID被解码成相应的结构。
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)
}