ObjectをDictionaryにする
Realm アドベントカレンダー三日目ですね.
ちっちゃな子ネタをどうぞ.
どれくらい思うことがあるのかわかりませんが,RealmのObjectをDictionaryとかに戻したい,相互変換したいって思ったことはありませんか?
私はあります.
import RealmSwift
extension Object {
func toDictionary() -> Dictionary<String, AnyObject> {
let properties = self.objectSchema.properties.map { $0.name }
let dictionary = self.dictionaryWithValuesForKeys(properties)
let mutabledic = NSMutableDictionary()
mutabledic.setValuesForKeysWithDictionary(dictionary)
for prop in self.objectSchema.properties as [Property]! {
if let nestedObject = self[prop.name] as? Object {
mutabledic.setValue(nestedObject.toDictionary() as NSDictionary, forKey: prop.name)
} else if let nestedListObject = self[prop.name] as? ListBase {
var objects = [AnyObject]()
for index in 0..<nestedListObject._rlmArray.count {
let object = nestedListObject._rlmArray[index] as AnyObject
objects.append(object.toDictionary() as NSDictionary)
}
mutabledic.setObject(objects, forKey: prop.name)
}
}
return mutabledic as NSDictionary as! Dictionary<String, AnyObject>
}
}
簡単に解説してみると
let properties = self.objectSchema.properties.map { $0.name }
let dictionary = self.dictionaryWithValuesForKeys(properties)
let mutabledic = NSMutableDictionary()
mutabledic.setValuesForKeysWithDictionary(dictionary)
このあたりで,Realm固有の型以外をだいたいNSMutableDictionaryにコピーできています.
objectSchema.properties
でObjectのschemaを取得できます.
dictionaryWithValuesForKeys(properties)
でSchemaをザザっとNSDictionaryにコピーできてしまいます.
ここから下は,再帰したりしながらListBaseや,ObjectをDictionary化していくコードですね.
ついでに,Camel CaseをSnake Caseに変換するコードも用意しました.
extension String {
func snakeCaseString() -> String {
var result = ""
self.characters.forEach( { char in
let string = "\(char)" as NSString
result += string.isEqualToString(string.capitalizedString) ? "_\(string.lowercaseString)" : "\(char)"
})
return result
}
やっていることは超単純で,文字を一文字づつチェックして,大文字だったら"_小文字"に置き換えるだけというものです.これでだいたいsnake caseにできちゃいます.
そして,このあたりを組み合わせてJSONにするとかすれば
API -> Object -> Dictionary -> JSON -> API
みたいな流れがすごくやりやすくなるかと思います.
私の場合は
APIKit → Himotoki → Object → Dictionary → Himotoki
みたいな変換をちらほらしています