在花了太多时间试图找到最佳实践之后,我再次寻求一些帮助,希望我不是唯一一个在这方面苦苦挣扎的人:
我有这样的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
}
我与会员实体有关系:
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
}
我要做的是使用NSJSONSerialization.dataWithJSONObject将我的Credential对象序列化为JSON,以生成我的JSON并将其POST到服务器。
但是,我在序列化对象时遇到错误,我相信这是因为我的对象不尊重这个(来自Apple文档):
可以转换为JSON的对象必须具有以下属性:
那么如何将我的对象序列化为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 :(得分:5)
我尝试了同样的但是无法通过一对一和一对多关系获得成功。所以我编写了一个解析器来将托管对象转换为字典和数组。你可以使用它;
//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
答案 1 :(得分: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
答案 2 :(得分:1)
答案 3 :(得分:0)
随着时间的推移,这个答案可能已经过时了,但你是否已经探讨了
的用法func URIRepresentation() -> NSURL
如果要重新构建ObjectID,则使用
func managedObjectIDForURIRepresentation(_ url: NSURL) -> NSManagedObjectID?
来自您的NSPersistentStoreCoordinator实例。
答案 4 :(得分:0)
我将@JSBach的答案更新为Swift 5。
import CoreData
class ManagedParser {
private var parsedObjs = NSMutableSet()
func convertToArray(managedObjects: NSArray?, parentNode: String? = nil) -> NSArray {
let resultArray = NSMutableArray()
if let managedObjects = managedObjects as? [NSManagedObject] {
for managedObject in managedObjects {
if self.parsedObjs.member(managedObject) == nil {
self.parsedObjs.add(managedObject)
resultArray.add(self.convertToDictionary(managedObject: managedObject,
parentNode: parentNode))
}
}
}
return resultArray
}
func convertToDictionary(managedObject: NSManagedObject, parentNode: String? = nil) -> NSDictionary {
let resultDictonary = NSMutableDictionary()
let entity = managedObject.entity
let properties: [String] = (entity.propertiesByName as NSDictionary).allKeys as? [String] ?? []
let parentNode = parentNode ?? managedObject.entity.name!
for property in properties {
if property.caseInsensitiveCompare(parentNode) != .orderedSame {
let value = managedObject.value(forKey: property)
if let set = value as? NSSet {
resultDictonary[property] = self.convertToArray(managedObjects: set.allObjects as NSArray, parentNode: parentNode)
} else if let orderedset = value as? NSOrderedSet {
resultDictonary[property] = self.convertToArray(managedObjects: NSArray(array: orderedset.array), parentNode: parentNode)
} else if let vManagedObject = value as? NSManagedObject {
if self.parsedObjs.member(managedObject) == nil {
self.parsedObjs.add(managedObject)
if vManagedObject.entity.name != parentNode {
resultDictonary[property] = self.convertToDictionary(managedObject: vManagedObject, parentNode: parentNode)
}
}
} else if let vData = value {
resultDictonary[property] = vData
}
}
}
return resultDictonary
}
}