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

问题描述 投票:0回答:2

我有一个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"]
    }
}

请帮助我理解这个框架。

json swift objectmapper
2个回答
0
投票

您需要以下列方式创建。

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。

我希望这能帮到您。


0
投票

我知道它不会从字面上回答这个问题,但这是使用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)
}
© www.soinside.com 2019 - 2024. All rights reserved.