Dear Stackoverflowers,
I have a hindrance regarding using ObjectMapper, so lets get straight to the point.
I'm saving models as a temporary record in a SQLite table, in JSON form. Each model has a Type field that uniquely identifies to which Model type it maps to.
For instance, if we have Models Dog, Cat, Mouse conforming to the Animal protocol, there's a equivalent AnimalType (DogType, CatType, MouseType) enum, which is also a field in each of the Models. Once saved to the database, I'm having trouble figuring out a elegant way of mapping the JSON loaded from the database to an actual instance of a Model class.
What I'm currently doing is converting the JSON via NSJSONSerialization into a JSON dictionary and querying the dictionary for the Type. Once the Type's found, I switch through all Types, instantiating a related Mapper object and attempting to deserialize the object. I feel this is a brute-force approach and was thinking there might be a better way of approach this problem.
Conclusive :
Models : Dog, Cat, Mouse (conforming to Animal, has AnimalType requirement)
Enums : AnimalType (DogType, CatType, MouseType)
Problem : How to determine and correctly instantiate a Mapper object to deserialize the loaded JSON into a instance, other than manually inspecting each Type and instantiating a correct mapper.
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)
}
I wrote this while looking for a Swift equivalent of @JsonSubTypes
from Jackson for polymorphic mapping of JSON subclasses.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.