Swift ObjectMapper类型推断

时间:2016-05-03 14:12:03

标签: ios swift objectmapper

亲爱的Stackoverflowers,

我有使用ObjectMapper的障碍,所以让我们直截了当。

我将模型保存为SQLite表中的临时记录,采用JSON格式。每个模型都有一个Type字段,用于唯一标识它映射到的Model类型。

例如,如果我们有符合Animal协议的模型Dog,Cat,Mouse,则会有一个等效的AnimalType(DogType,CatType,MouseType)枚举,它也是每个模型中的一个字段。一旦保存到数据库,我就无法找到将从数据库加载的JSON映射到Model类的实际实例的优雅方法。

我目前正在做的是将JSON通过NSJSONSerialization转换为JSON字典并查询字典中的Type。找到Type后,我切换所有类型,实例化一个相关的Mapper对象并尝试反序列化该对象。我觉得这是一种蛮力的方法,并且认为可能有更好的方法来解决这个问题。

结论性

模型:狗,猫,老鼠(符合Animal,有AnimalType要求)

枚举:AnimalType(DogType,CatType,MouseType)

问题如何确定并正确实例化Mapper对象以将加载的JSON反序列化为实例,而不是手动检查每个Type并实例化正确的映射器。 < / p>

enum AnimalType {
    case Dog
    case Cat
    case Mouse
}

protocol Animal {
    var animalType: AnimalType { get }
}

struct Dog: Animal {
    var animalType = AnimalType.Dog
}

struct Cat: Animal {
    var animalType = AnimalType.Cat
}

struct Mouse: Animal {
    var animalType = AnimalType.Mouse
}

1 个答案:

答案 0 :(得分:1)

import ObjectMapper

enum AnimalType : String {
    case Cat = "Cat"
    case Dog = "Dog"
    case Mouse = "Mouse"
}

class Animal: StaticMappable, Mappable {
    var animalType: AnimalType?

    required init?(_ map: Map) {}

    init() {}

    func mapping(map: Map) {
        animalType <- (map["animalType"], EnumTransform<AnimalType>())
    }

    static func objectForMapping(map: Map) -> BaseMappable? {
        let typeString: String? = map["animalType"].value()
        if let typeString = typeString {
            let animalType: AnimalType? = AnimalType(rawValue: typeString)
            if let animalType = animalType {
                switch(animalType) {
                    case AnimalType.Cat: return Cat()
                    case AnimalType.Dog: return Dog()
                    case AnimalType.Mouse: return Mouse()
                }
            }
        }
        return Animal()
    }
}

class Cat: Animal {
    var purr: String?

    required init?(_ map: Map) {
        super.init(map)
    }

    override init() {
        super.init()
    }

    override func mapping(map: Map) {
        super.mapping(map)

        purr <- map["purr"]
    }
}

class Dog: Animal {
    var bark: String?
    var bite: String?

    required init?(_ map: Map) {
        super.init(map)
    }

    override init() {
        super.init()
    }

    override func mapping(map: Map) {
        super.mapping(map)

        bark <- map["bark"]
        bite <- map["bite"]
    }
}

class Mouse: Animal {
    var squeak: String?

    required init?(_ map: Map) {
        super.init(map)
    }

    override init() {
        super.init()
    }

    override func mapping(map: Map) {
        super.mapping(map)

        squeak <- map["squeak"]
    }
}

class Owner : Mappable {
    var name: String?
    var animal: Animal?

    required init?(_ map: Map) {}

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

let catJson = "{\"animalType\":\"Cat\",\"purr\":\"rrurrrrrurrr\"}"
let cat = Mapper<Cat>().map(catJson)
if let cat = cat {
    let catJSONString = Mapper().toJSONString(cat, prettyPrint: false)
}

let ownerJson = "{\"name\":\"Blofeld\", \"animal\":{\"animalType\":\"Cat\",\"purr\":\"rrurrrrrurrr\"}}"
let owner = Mapper<Owner>().map(ownerJson)
if let owner = owner {
    let ownerJSONString = Mapper().toJSONString(owner, prettyPrint: false)
}

我在寻找来自Jackson的Swift相当于@JsonSubTypes的JSON子类的多态映射时编写了这个。