2

Stackoverflowers 様

ObjectMapper の使用に支障があるので、本題に入ります。

モデルを一時レコードとして SQLite テーブルに JSON 形式で保存しています。各モデルには、マップ先のモデル タイプを一意に識別する Type フィールドがあります。

たとえば、Animal プロトコルに準拠するモデル Dog、Cat、Mouse がある場合、同等の AnimalType (DogType、CatType、MouseType) 列挙型があり、これは各モデルのフィールドでもあります。データベースに保存された後、データベースから読み込まれた JSON を Model クラスの実際のインスタンスにマッピングするエレガントな方法を見つけるのに苦労しています。

私が現在行っているのは、NSJSONSerialization を介して JSON を JSON ディクショナリに変換し、そのディクショナリにタイプのクエリを実行することです。タイプが見つかったら、すべてのタイプを切り替えて、関連する Mapper オブジェクトをインスタンス化し、オブジェクトのデシリアライズを試みます。これは強引なアプローチだと感じており、この問題にアプローチするより良い方法があるのではないかと考えていました。

結論

モデル: 犬、猫、マウス (Animal に準拠、AnimalType 要件あり)

Enums : AnimalType (DogType、CatType、MouseType)

問題:各タイプを手動で検査して正しいマッパーをインスタンス化する以外に、ロードされた JSON をインスタンスに逆シリアル化するために 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
}
4

1 に答える 1

4
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)
}

@JsonSubTypesJSON サブクラスのポリモーフィック マッピング用の Jackson に相当する Swift を探しながら、これを書きました。

于 2016-09-10T07:30:20.860 に答える