iOS-Swift: Сериализовать NSManagedObject для JSON (с отношениями)

Проведя слишком много времени, пытаясь найти лучшие практики, здесь я снова прошу о помощи, надеясь, что я не единственный, кто борется с этим:

У меня есть NSManaged Objects, подобные этим:

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 } 

У меня есть отношения с Entity Entity:

 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 и POST его на сервер.

Тем не менее, у меня есть ошибка при сериализации моего объекта, и я считаю, что это потому, что мой объект не соблюдает это (из документации Apple):

Объект, который может быть преобразован в JSON, должен иметь следующие свойства:

  • Объект верхнего уровня – NSArray или NSDictionary.
  • Все объекты являются экземплярами NSString, NSNumber, NSArray, NSDictionary или NSNull.
  • Все словарные ключи являются экземплярами NSString.
  • Числа не NaN или бесконечность.

Итак, как я могу сериализовать свой объект JSON? Должен ли я найти способ преобразования члена в словарь, а затем попытаться найти способ установить этот словарь в качестве значения для моих отношений с учетными данными?

Пропустил ли я встроенный картограф, который его обрабатывает?

Прошу прощения, если это не ясно, но любая помощь будет очень приятной.

Заранее благодарю вас.

Хьюго

EDIT :

Как было предложено в ответе, я попытался извлечь словарь вместо 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) /*******************************/ 

4 Solutions collect form web for “iOS-Swift: Сериализовать NSManagedObject для JSON (с отношениями)”

Я пробовал то же самое, но не смог добиться успеха в отношениях один к одному и от одного до многих. Поэтому я написал парсер для преобразования управляемых объектов в словарь и массив. Вы можете использовать его;

 //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; } //FE 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; } //FE } //CLS END 

Я пересмотрел ответ @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; } //FE 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; } //FE } //CLS END 

Вы можете достичь этого, используя стороннюю структуру, такую ​​как Groot или Sync .

С течением времени этот ответ может быть устаревшим, но вы изучили использование

 func URIRepresentation() -> NSURL 

из класса NSManagedObjectID? После того, как у вас есть URL-адрес, вы можете превратить его в String, чтобы поместить в свой JSON-объект, что означает, что он будет сериализоваться должным образом. При соответствующей структуре вокруг этих ключей, отношения могут быть экспортированы.

Когда вы хотите восстановить ObjectID, вы затем используете

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

из вашего экземпляра NSPsistentStoreCoordinator.

  • Попытка использования учебника по серверу Realm Object Server
  • Идентификатор базового идентификатора данных
  • Шифрование и синхронизация iOS Swift Realm с сервером
  • Swift 3: невозможно подключиться к периферии через BLE
  • Как добавить маленький значок ниже выбранного значка UITabBarItem в Swift
  • Удалить элемент в массиве без жесткого кодирования индекса? в Свифт
  • Автоматически устанавливать центр uibutton - SWIFT
  • Значок MKMapItem недоступен в быстром
  • Swift: UIPercentDrivenInteractiveTransition при отмене?
  • Swift3 Случайный метод расширения
  • Самый простой способ принудительного сбоя в Swift
  • Interesting Posts

    Пользовательские шрифты в iOS 7

    Значки символов Xcode … окончательный список?

    Как получить левую прописку на изображении UITextField leftView?

    Подкласс и использование UIActivityItemProvider с помощью UIActivityViewController

    Приложение iOS выделяет все больше и больше памяти

    Насколько легко узнать Flex или ActionScript, а какой лучше?

    Метод работает правильно при вызове из своего класса, но не в противном случае

    ios: загрузка новых данных в UICollectionView

    «Выполнение дорогостоящей бездонной операции!» – что это такое и как его исправить?

    iOS7 UISearchBar текст кнопки отмены не отображается. Кнопка выглядит невидимой

    Невозможно исправить анимацию Auto Layout во время события поворота

    включить отсканировку только для одного направления UITableView

    Ошибка при попытке удалить узел из родителя с помощью быстрого перечисления

    Пользовательский интерфейс UIWindow на iOS 8.3 iPad работает на симуляторе, но не на устройстве

    Внедрение ZBar QR Code Reader в UIView

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.