iOS-Swift:将NSManagedObject序列化为JSON(使用关系) [英] iOS-Swift : Serialize a NSManagedObject to JSON (with relationships)

查看:180
本文介绍了iOS-Swift:将NSManagedObject序列化为JSON(使用关系)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在花了太多时间寻找最佳做法后,我再次要求您提供一些帮助,希望我不是唯一一个与此有关的人:



  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

类成员: 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到服务器。



但是,序列化我的对象时出现错误,我相信这是因为我的对象不尊重这一点(从苹果文档):



可以转换为JSON的对象必须具有以下属性:




  • 顶层对象是NSArray或NSDictionary。

  • 所有对象都是NSString,NSNumber, NSArray,NSDictionary或NSNull。

  • 所有字典键都是NSString的实例。

  • 数字不是NaN或无穷大。



那么如何将我的对象序列化为JSON?我应该找到某种方法将会员转换为字典,然后尝试找到一种方法来设置这个字典作为我与证书的关系的值?



有我错过了处理它的内置映射器?



对不起,如果不清楚,任何帮助将是非常好的。



提前,谢谢。



Hugo



>:



如答案中所示,我试图获取字典而不是NSManagedObject,但记录的字典是空的(但是,相同的代码工作非常简单类有几个字符串属性,没有关系),这里是代码:

  / ********* ********************** 
TEST:Fetch字典,而不是NSManagedObject

* /

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

//创建凭据实体
let newMember = NSEntityDescription.insertNewObjectForEntityForName(Member,inManagedObjectContext:self.managedObjectContext!)as!会员

//实例化一些字段
newCredential.credentialId =44444
newMember.memberFirstName =TEST

//设置关系
newCredential.credentialMember = newMember

//检索currentCredential
让requestGuest = NSFetchRequest(entityName:Credential)

//获取字典NSManagedObject
requestGuest.resultType = NSFetchRequestResultType.DictionaryResultType

let fetchedGuest =(managedObjectContext!.executeFetchRequest(requestGuest,error:nil))! //不需要在这里投?

println(fetchedGuest.description)

/ ************************* **** /


解决方案

没有成功与一对一和一对多的关系。所以我写了一个解析器来将托管对象转换为字典和数组。

  //在xCode 6.4上测试 -  Swift 1.2 
让requestGuest = NSFetchRequest(entityName: Credential)
let fetchedGuest =(managedObjectContext!.executeFetchRequest(requestGuest,error:nil))!

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

// -

  // 
// ManagedParser.swift
//由Shoaib于7/29/15创建。
//

import UIKit
import CoreData

class ManagedParser:NSObject {


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

var rtnArr:NSMutableArray = NSMutableArray();
// -
如果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;
让属性:[String] =(entity.propertiesByName as NSDictionary).allKeys as! [串];
// -
let parentNode:String = parentNode? managedObject.entity.name !;
for property:属性中的字符串{
if(property.caseInsensitiveCompare(parentNode)!= NSComparisonResult.OrderedSame)
{
让值:AnyObject? = managedObject.valueForKey(property);
// -
如果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


After spending too much time trying to find the best practices, here I am once again asking for some help, hoping I am not the only one struggling with this :

I have NSManaged Objects like these :

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

}

I have a relationship with a Member 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

}

What I am trying to do is to serialize my Credential object to JSON using NSJSONSerialization.dataWithJSONObject to generate my JSON and POST it to a Server.

However, I've got an error while serializing my object, and I believe this is because my object does not respect this (from Apple documentation) :

An object that may be converted to JSON must have the following properties:

  • The top level object is an NSArray or NSDictionary.
  • All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
  • All dictionary keys are instances of NSString.
  • Numbers are not NaN or infinity.

So how can I Serialize my Object to JSON ? Should I find some way to convert a Member to a Dictionary, then try to find a way to set this dictionary as the value for my relationship with a credential ?

Have I missed a built-in mapper that handles it ?

I am sorry if that is not clear but any help would be very nice.

In advance, thank you.

Hugo

EDIT :

As suggested in an answer, I tried to fetch a dictionary instead of a NSManagedObject but the logged dictionary is empty (however, the same code worked for a very simple class with a few string attributes and no relationship), here is the code :

/*******************************
    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)

    /*******************************/

解决方案

I tried the same but could not get succeed with one to one and one to many relationships. So I wrote a parser to convert managed objects to dictionary and array. You may use it;

//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

这篇关于iOS-Swift:将NSManagedObject序列化为JSON(使用关系)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆