2016-06-07 226 views
1

我有一個嵌套的Realm對象,在嵌套對象中有多個嵌套的NSDate屬性。我正在使用this answer將嵌套的Realm對象轉換爲NSDictionary,但我不知道如何將該NSDictionary轉換爲實際的JSON。如何將Realm對象轉換爲嵌套NSDate屬性的JSON?

當我使用NSJSONSerialization.dataWithJSONObject(),我得到的錯誤:'Invalid type in JSON write (__NSTaggedDate)'

據我瞭解,我必須先將NSDate屬性轉換爲NSString。問題是我不知道如何進入深度嵌套的對象來做到這一點。

此代碼生成'Invalid type in JSON write (__NSTaggedDate)'錯誤:

let exercises = realm.objects(ExerciseProgram).first 

    let dic = exercises!.toDictionary() 

    do { 
     if let postData: NSData = try NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted) { 
      let json = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String 
      print(json) 
     } 

    } catch let error as NSError { 
     print(error) 

我的物體的簡化版本:

final class ExerciseProgram: Object { 

    dynamic var name: String = "" 
    dynamic var startDate = NSDate() 
    dynamic var userProfile: User? 
    var program = List<Exercise>() 

} 

final class Exercise: Object { 

    dynamic var name = "" 
    dynamic var notes: String? 
    var workoutDiary = List<Workout>() 
    dynamic var goal = 0 

} 

final class Workout: Object { 

    dynamic var date = NSDate() 
    var sets = List<WorkSet>() 

} 

回答

1

JSON序列與iOS」默認串行器是相當嚴格的,並且大多數類型(包括NSDate)不能直接序列化。

我看了一下Eugene在這個問題中發佈的令人敬畏的代碼示例(看起來實際上是從另一個原始問題中派生出來的)。對象的深度似乎並不重要,因爲看起來這個擴展巧妙地設置爲在較低級別上遞歸地調用它自己。

現在,它只是簡單地將NSDate值複製到字典中,但您可以輕鬆地將其他情況添加到條件列表中,以檢測任何NSDate對象,並將它們轉換爲字符串。這會自動覆蓋已經在字符串版本中的NSDate值:

extension Object { 
func toDictionary() -> NSDictionary { 
    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]! { 
     // find lists 
     if let nestedObject = self[prop.name] as? Object { 
      mutabledic.setValue(nestedObject.toDictionary(), 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()) 
      } 
      mutabledic.setObject(objects, forKey: prop.name) 
     } 
     else if let dateObject = self[prop.name] as? NSDate { 
      let dateString = ... ; //Perform the conversion you want here 
      mutabledic.setValue(dateString, forKey: prop.name) 
     }  
    } 
    return mutabledic 
} 

}