2015-07-28 54 views
4

在花費了太多時間來尋找最佳實踐之後,在這裏我再次尋求一些幫助,希望我不是唯一一個正在努力的人:iOS-Swift:將NSManagedObject序列化爲JSON(有關係)

我已經NSManaged對象這樣的:

import Foundation 
import CoreData 

class Credential: NSManagedObject { 

    @NSManaged var credentialArrivalDate: String? 
    @NSManaged var credentialBarCode: String? 
    @NSManaged var credentialComment: String? 
    @NSManaged var credentialCountCheckIn: Int 
    @NSManaged var credentialCountCheckOut: Int 
    @NSManaged var credentialDepartureDate: String? 
    @NSManaged var credentialId: String? 
    @NSManaged var credentialIsArrived: Bool 
    @NSManaged var credentialIsCheckedOut: Bool 
    @NSManaged var credentialIsHost: Bool 
    @NSManaged var credentialLastModificationDate: String? 
    @NSManaged var credentialMemberControlled: String? 
    @NSManaged var credentialNumberOfPeople: Int 
    @NSManaged var credentialRSVP: Int 
    @NSManaged var credentialTypeId: String? 
    @NSManaged var credentialTypeName: String? 
    @NSManaged var credentialZoneId: String? 
    @NSManaged var credentialZoneName: String? 
    @NSManaged var credentialHosts: Set<Host>? 
    @NSManaged var credentialMember: Member 
    @NSManaged var credentialExtensionFields: Set<ExtensionFields>? 
    @NSManaged var credentialDeltaFirstCheckIn: String? 
    @NSManaged var credentialDeltaFirstCheckOut: String? 
    @NSManaged var credentialIsCheckedIn: Bool 

} 

我有一個會員實體的關係:

import Foundation 
import CoreData 

class Member: NSManagedObject { 

    @NSManaged var memberCompany: String 
    @NSManaged var memberEMail: String 
    @NSManaged var memberFirstName: String 
    @NSManaged var memberId: String 
    @NSManaged var memberJob: String 
    @NSManaged var memberLastModificationDate: String 
    @NSManaged var memberLastName: String 
    @NSManaged var memberPhoneNumber: String 
    @NSManaged var memberTitle: String 
    @NSManaged var memberCredential: Credential 

} 

我所試圖做的是連載我的Credential對象到JSON使用NSJSONSerialization.dataWithJSONObject生成我的JSON並將其張貼到服務器。

不過,雖然我的序列化對象,我得到一個錯誤,我相信這是因爲我的對象不尊重這個(蘋果文件):

可以轉換成JSON對象必須有以下屬性:

  • 頂層對象是NSArray或NSDictionary。
  • 所有對象都是NSString,NSNumber,NSArray,NSDictionary或NSNull的實例。
  • 所有的字典鍵都是NSString的實例。
  • 數字不是NaN或無窮大。

那麼如何將我的對象序列化爲JSON?我是否應該找到某種方法將會員轉換爲字典,然後嘗試找到一種方法將此字典設置爲我與證書關係的值?

我錯過了一個處理它的內置映射器嗎?

對不起,如果不明確,但任何幫助將是非常好的。

提前,謝謝。

雨果

編輯

作爲一個答案的建議,我想取一本字典,而不是一個NSManagedObject,但記錄的字典是空的(但是,相同的代碼工作了一個非常簡單的有幾個字符串的屬性和沒有關係的類),這裏是代碼:

/******************************* 
    TEST : Fetch dictionary instead of NSManagedObject 

    */ 

    // create Credential entity 
    let newCredential = NSEntityDescription.insertNewObjectForEntityForName("Credential", inManagedObjectContext: self.managedObjectContext!) as! Credential 

    // create Credential entity 
    let newMember = NSEntityDescription.insertNewObjectForEntityForName("Member", inManagedObjectContext: self.managedObjectContext!) as! Member 

    // instanciate some fields 
    newCredential.credentialId = "44444" 
    newMember.memberFirstName = "TEST" 

    // set the relationship 
    newCredential.credentialMember = newMember 

    // retrieve currentCredential 
    let requestGuest = NSFetchRequest(entityName: "Credential") 

    // get a dictionary instead of NSManagedObject 
    requestGuest.resultType = NSFetchRequestResultType.DictionaryResultType 

    let fetchedGuest = (managedObjectContext!.executeFetchRequest(requestGuest, error:nil))! // no need to cast here ? 

    println(fetchedGuest.description) 

    /*******************************/ 
+0

你看過第三方框架,像RestKit? – Wain

+0

使用fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType從coredata中獲取字典中的數據,然後將其序列化爲json。 – Shoaib

+0

JSON映射器不是太多嗎? +我寧願儘可能使用swift – H4Hugo

回答

4

我試過相同的,但沒能有一對一和一對多的關係成功。所以我寫了一個解析器來將託管對象轉換爲字典和數組。你可以使用它;

//Tested on xCode 6.4 - Swift 1.2 
let requestGuest = NSFetchRequest(entityName: "Credential") 
let fetchedGuest = (managedObjectContext!.executeFetchRequest(requestGuest, error:nil))! 

let dataInArr:NSArray = ManagedParser.convertToArray(fetchedGuest); 
NSLog("dataInArr \(dataInArr)"); 

// -

// 
// ManagedParser.swift 
// Created by Shoaib on 7/29/15. 
// 

import UIKit 
import CoreData 

class ManagedParser: NSObject { 


    class func convertToArray(managedObjects:NSArray?, parentNode:String? = nil) -> NSArray { 

     var rtnArr:NSMutableArray = NSMutableArray(); 
     //-- 
     if let managedObjs:[NSManagedObject] = managedObjects as? [NSManagedObject] { 
      for managedObject:NSManagedObject in managedObjs { 
       rtnArr.addObject(self.convertToDictionary(managedObject, parentNode: parentNode)); 
      } 
     } 

     return rtnArr; 
    } //F.E. 

    class func convertToDictionary(managedObject:NSManagedObject, parentNode:String? = nil) -> NSDictionary { 

     var rtnDict:NSMutableDictionary = NSMutableDictionary(); 
     //- 
     let entity:NSEntityDescription = managedObject.entity; 
     let properties:[String] = (entity.propertiesByName as NSDictionary).allKeys as! [String]; 
     //-- 
     let parentNode:String = parentNode ?? managedObject.entity.name!; 
     for property:String in properties { 
      if (property.caseInsensitiveCompare(parentNode) != NSComparisonResult.OrderedSame) 
      { 
       let value: AnyObject? = managedObject.valueForKey(property); 
       //-- 
       if let set:NSSet = value as? NSSet { 
        rtnDict[property] = self.convertToArray(set.allObjects, parentNode: parentNode); 
       } else if let vManagedObject:NSManagedObject = value as? NSManagedObject { 

        if (vManagedObject.entity.name != parentNode) { 
         rtnDict[property] = self.convertToDictionary(vManagedObject, parentNode: parentNode); 
        } 
       } else if let vData:AnyObject = value { 
        rtnDict[property] = vData; 
       } 
      } 
     } 

     return rtnDict; 
    } //F.E. 


} //CLS END 
+0

謝謝,我試過了你的解析器,但是在這一行我得到了一個EXC_BAD_ACCESS錯誤代碼= 2:let properties:[String] =(entity.propertiesByName as NSDictionary).allKeys as! [串]; – H4Hugo

+0

@HugoRiffiod;結帳更新類/功能 – Shoaib

+0

謝謝,它工作得更好,但輸出數組不完整,是因爲我沒有提供每個值?下面是結果:dataInArr( { credentialCountCheckIn = 0; credentialCountCheckOut = 0; credentialExtensionFields =( ); credentialHosts =( ); credentialId = 1; credentialNumberOfPeople = 0; credentialRSVP = 0; } ) – H4Hugo

1

你可以使用第三方框架狀GrootSync實現這一目標。

0

隨着時間的推移,這個答案可能是過時的,但你探索從NSManagedObjectID類使用

func URIRepresentation() -> NSURL 

?一旦你有一個URL,你可以把它轉換成一個字符串放入你的JSON對象,這意味着它將正確地序列化。通過圍繞這些鍵的適當結構,可以導出關係。

當你想重建的對象ID,你再使用

func managedObjectIDForURIRepresentation(_ url: NSURL) -> NSManagedObjectID? 

從NSPersistentStoreCoordinator的實例。

2

我修改了@Shoaib的答案,因爲在CoreData上我有雙向關係導致了這個無限循環。 現在這可以防止使用對象集來處理兩次相同的NSManagedObject。

// 
// ManagedParser.swift 
// Created by Shoaib on 7/29/15. 
// http://stackoverflow.com/questions/31672558/ios-swift-serialize-a-nsmanagedobject-to-json-with-relationships 
// Mod by dkavraal on 7/28/16 
// 

import CoreData 

class ManagedParser: NSObject { 
    private var parsedObjs:NSMutableSet = NSMutableSet(); 

    func convertToArray(managedObjects:NSArray?, parentNode:String? = nil) -> NSArray { 
     let rtnArr:NSMutableArray = NSMutableArray(); 
     //-- 
     if let managedObjs:[NSManagedObject] = managedObjects as? [NSManagedObject] { 
      for managedObject:NSManagedObject in managedObjs { 
       if self.parsedObjs.member(managedObject) == nil { 
        self.parsedObjs.addObject(managedObject); 
        rtnArr.addObject(self.convertToDictionary(managedObject, parentNode: parentNode)); 
       } 
      } 
     } 

     return rtnArr; 
    } //F.E. 

    func convertToDictionary(managedObject:NSManagedObject, parentNode:String? = nil) -> NSDictionary { 
     let rtnDict:NSMutableDictionary = NSMutableDictionary(); 
     //- 
     let entity:NSEntityDescription = managedObject.entity; 
     let properties:[String] = (entity.propertiesByName as NSDictionary).allKeys as? [String] ?? []; 
     //-- 
     let parentNode:String = parentNode ?? managedObject.entity.name!; 
     for property:String in properties { 
      if (property.caseInsensitiveCompare(parentNode) != NSComparisonResult.OrderedSame) 
      { 
       let value: AnyObject? = managedObject.valueForKey(property); 
       //-- 
       if let set:NSSet = value as? NSSet { 
        rtnDict[property] = self.convertToArray(set.allObjects, parentNode: parentNode); 
       } else if let orderedset:NSOrderedSet = value as? NSOrderedSet { 
        rtnDict[property] = self.convertToArray(NSArray(array: orderedset.array), parentNode: parentNode); 
       } else if let vManagedObject:NSManagedObject = value as? NSManagedObject { 
        if self.parsedObjs.member(managedObject) == nil { 
         self.parsedObjs.addObject(managedObject); 
         if (vManagedObject.entity.name != parentNode) { 
          rtnDict[property] = self.convertToDictionary(vManagedObject, parentNode: parentNode); 
         } 
        } 
       } else if let vData:AnyObject = value { 
        rtnDict[property] = vData; 
       } 
      } 
     } 

     return rtnDict; 
    } //F.E. 


} //CLS END