如何使用ObjectMapper映射不同的类型?

时间:2017-07-26 15:08:52

标签: json swift objectmapper

我正在使用ObjectMapper将我的JSON映射到Swift对象。

我有以下Swift对象:

class User: Mappable {

    var name: String?
    var val: Int?

    required init?(map: Map) { }

    func mapping(map: Map) {
        name <- map["name"]
        val  <- map["userId"]
    }
}

我有这个JSON结构:

{
   "name": "first",
   "userId": "1" // here is `String` type.
},
{
   "name": "second",
   "userId": 1 // here is `Int` type.
}

映射JSON后,userIdUser的{​​{1}}为name为空。

如何将"first"映射到Int/String

3 个答案:

答案 0 :(得分:2)

在阅读ObjectMapper的代码后,我找到了一种更简单的方法来解决问题,就是自定义转换。

public class IntTransform: TransformType {

    public typealias Object = Int
    public typealias JSON = Any?

    public init() {}

    public func transformFromJSON(_ value: Any?) -> Int? {

        var result: Int?

        guard let json = value else {
            return result
        }

        if json is Int {
            result = (json as! Int)
        }
        if json is String {
            result = Int(json as! String)
        }

        return result
    }

    public func transformToJSON(_ value: Int?) -> Any?? {

        guard let object = value else {
            return nil
        }

        return String(object)
    }
}

然后,使用自定义转换到mapping函数。

class User: Mappable {

    var name: String?
    var userId: Int?

    required init?(map: Map) { }

    func mapping(map: Map) {
        name   <- map["name"]
        userId <- (map["userId"], IntTransform()) // here use the custom transform.
    }
}

希望它可以帮助那些遇到同样问题的人。 :)

答案 1 :(得分:1)

您应该改进您的API。但是,如果您不能这样做,请尝试以下代码:

class User: Mappable {

    var name: String?
    var val: Int?

    required init?(map: Map) { }

    func mapping(map: Map) {
        name <- map["name"]

        // 1: Get the value of JSON and store it in a variable of type Any?
        var userIdData: Any?
        userIdData <- map["userId"]

        // 2: Check the value type of the value and convert to Int type
        if userIdData is Int {
            val = (userIdData as! Int) 
        } else if userIdData is String {
            val = Int(userIdData as! String) 
        }
    }
}

您可以参考此文档:Type Casting

答案 2 :(得分:1)

如果你的API是这样的 - 这是非常糟糕的API。你能做的是有两个变量而不是一个:

class User: Mappable {

    var name: String?
    var valInt: Int?
    var valString: String?

    required init?(map: Map) { }

    func mapping(map: Map) {
        name <- map["name"]
        valInt  <- map["val"]
        valString <- map["val"]
    }
}

您甚至可以添加能够获得如下价值的功能:

// bellow func mapping(map: Map){
func getUserId() -> String {
     if(self.valInt != nil) {
         return "\(valInt!)"
     }
     else {
         return valString!
     }
}

或者,使用if:

func getUserId() -> String {
     if let userId  = self.valInt {
         return "\(userId)"
     }
     if let userId = valString {
         return userId
     }
     return ""
}

或者稍后使用选项,您可以使用if let userId = object.getUserId()

func getUserId() -> String? {
     if(self.valInt != nil) {
         return String(valInt)
     }
     else {
         return valString
     }
}