[英]Swift ObjectMapper type inference
亲爱的 Stackoverflowers,
我在使用 ObjectMapper 时遇到了障碍,所以让我们直接切入正题。
我将模型以 JSON 格式保存为 SQLite 表中的临时记录。 每个模型都有一个类型字段,用于唯一标识它映射到的模型类型。
例如,如果我们有符合 Animal 协议的模型狗、猫、鼠标,则有一个等效的 AnimalType (DogType, CatType, MouseType) 枚举,它也是每个模型中的一个字段。 一旦保存到数据库中,我就无法找到一种优雅的方法来将 JSON 从数据库加载到 Model 类的实际实例。
我目前正在做的是通过 NSJSONSerialization 将 JSON 转换为 JSON 字典并查询该字典的类型。 找到类型后,我会切换所有类型,实例化相关的 Mapper 对象并尝试反序列化该对象。 我觉得这是一种蛮力方法,并且认为可能有更好的方法来解决这个问题。
结论:
模型:狗,猫,老鼠(符合动物,有动物类型要求)
枚举:AnimalType(DogType、CatType、MouseType)
问题:如何确定并正确实例化 Mapper 对象以将加载的 JSON 反序列化为实例,而不是手动检查每个类型并实例化正确的映射器。
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
}
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 的@JsonSubTypes
的 Swift 等价物时写了这个,用于 JSON 子类的多态映射。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.