LoginSignup
31
33

More than 5 years have passed since last update.

ObjectMapperでネスト化されたオブジェクトを扱う

Last updated at Posted at 2015-07-24

Objc/SwiftでORMはこれまで使ったことがなかったのですが、手始めにObjectMapperというものを使ってみた。

使い方はREADME.mdに書いてある通りなので省略するとして、

sample.json
"group" {
  "id" : 1234,
  "name" : "spacemen3",
  "color" : 3
  "owner" : {
    "id" : 99999,
    "name" : "ushisantoasobu",
    "url" : "xxx.png"
  }
}

こんな感じでネスト化されたjsonオブジェクトの、例えばownernameにアクセスしたい場合は、

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

のような感じでドットでつなぐことでマッピングできる(これもREADME.mdに書いてある)。

でもこういったデータ構造を扱うときって、

Group.swift
class Group: Mappable {

    var identifier      = Dynamic<Int>(0)
    var name            = Dynamic<String>("")
    var color           = Dynamic<Int>(0)
    var ownerId         = Dynamic<Int>(0)  
    var ownerName       = Dynamic<String>("")
    var ownerUrl        = Dynamic<String>("")

    required init?(_ map: Map) {
        mapping(map)
    }

    func mapping(map: Map) {
        identifier.value      <- map["id"]
        name.value            <- map["name"]
        color.value           <- map["color"]
        ownerId.value         <- map["owner.id"]
        ownerName.value       <- map["owner.name"]
        ownerUrl.value        <- map["owner.url"]
    }
}

とやることはなくて、

User.swift
class User: Mappable {

    var identifier      = Dynamic<Int>(0)
    var name            = Dynamic<String>("")
    var url             = Dynamic<String>("")

    required init?(_ map: Map) {
        mapping(map)
    }

    func mapping(map: Map) {
        identifier.value      <- map["id"]
        name.value            <- map["name"]
        url.value             <- map["url"]
    }
}
Group.swift
class Group: Mappable {

    var identifier      = Dynamic<Int>(0)
    var name            = Dynamic<String>("")
    var color           = Dynamic<Int>(0)
    var owner           = User()  

    required init?(_ map: Map) {
        mapping(map)
    }

    func mapping(map: Map) {
        identifier.value      <- map["id"]
        name.value            <- map["name"]
        color.value           <- map["color"]
        user                  = Mapper<User>().map(dictionary["owner"]) // ここは雰囲気で書いたので当然エラー
    }
}

こんな感じで書くのが、データ構造としてスッキリするので普通だと思う。これはあくまで雰囲気で書いたもので、ここをどうやって正しく・簡潔に書くことができるか迷っていた。

で、自分がいまやっているのは、

User.swift
class User: Mappable {

    var prefix = ""

    var identifier      = Dynamic<Int>(0)
    var name            = Dynamic<String>("")
    var url             = Dynamic<String>("")

    required init?(_ map: Map) {
        mapping(map)
    }

    init(_ map: Map, prefix :String) {
        self.prefix = prefix + "."
        mapping(map)
    }

    func mapping(map: Map) {
        identifier.value      <- map[prefix + "id"]
        name.value            <- map[prefix + "name"]
        url.value             <- map[prefix + "url"]
    }
}
Group.swift
class Group: Mappable {

    var prefix = ""

    var identifier      = Dynamic<Int>(0)
    var name            = Dynamic<String>("")
    var color           = Dynamic<Int>(0)
    var owner           = User()  

    required init?(_ map: Map) {
        mapping(map)
    }

    init(_ map: Map, prefix :String) {
        self.prefix = prefix + "."
        mapping(map)
    }

    func mapping(map: Map) {
        identifier.value      <- map["id"]
        name.value            <- map["name"]
        color.value           <- map["color"]
        user                  = User(map, prefix: prefix + "owner")
    }
}

こんな感じでやっちゃってる。prefixだとかinit(_ map: Map, prefix :String) {は全部共通なので基底クラスがつくれると思うけど、現在思考錯誤中なのでまだやっていない。

でも多分もっといい方法があるのだと思う。ので、ご教授いただけたら幸いです。いや、そもそもObjectMapper自体そんな使われてないのかな。。

追記(2015/7/26)

@keitaoouchi さんよりご指摘いただいて、シンプルに

Group.swift
    func mapping(map: Map) {
        identifier.value      <- map["id"]
        name.value            <- map["name"]
        color.value           <- map["color"]
        user                  <- map["owner"]
    }

でいけました。。。ありがとうございました!

追記(2015/8/2)

リストのモデルもそういえばやってなかったと思ったのですが、すんなりいけた。

    var members    = [Member]()

    func mapping(map: Map) {
        identifier.value      <- map["id"]
        name.value            <- map["name"]
        color.value           <- map["color"]
        user                  <- map["owner"]
        members               <- map["members"]
    }
31
33
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
33