使用Swift中ObjectMapper中的TranfsformType映射类对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Swift中ObjectMapper中的TranfsformType映射类对象相关的知识,希望对你有一定的参考价值。

我有一个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)

以上是关于使用Swift中ObjectMapper中的TranfsformType映射类对象的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 嵌套对象的映射 (Objectmapper)

无法在 Swift 中导入 ObjectMapper

swift Demo使用ObjectMapper映射json

在 Swift 中将 Alamofire 结果解析为对象(使用:Alamofire、SwiftyJSON 和 ObjectMapper)

Swift 3 ObjectMapper - 将 URLSession 结果转换为 Map 对象失败

Swift 和 ObjectMapper:具有最小值的 NSDate