Iphone NSJSONSerialization错误-JSON写入(菜单)中的类型无效

Iphone NSJSONSerialization错误-JSON写入(菜单)中的类型无效,iphone,objective-c,json,serialization,ios5,Iphone,Objective C,Json,Serialization,Ios5,我有一个应用程序使用的核心数据与3个实体具有非常相似的属性。这种关系包括: 分支->>菜单->>类别->>FoodItem 每个实体都有一个关联的类:示例 我试图在sqlite数据库中生成数据的JSON表示。 //gets a single menu record which has some categories and each of these have some food items id obj = [NSArray arrayWithObject:[[DataStore singl

我有一个应用程序使用的核心数据与3个实体具有非常相似的属性。这种关系包括:

分支->>菜单->>类别->>FoodItem

每个实体都有一个关联的类:示例

我试图在sqlite数据库中生成数据的JSON表示。

//gets a single menu record which has some categories and each of these have some food items
id obj = [NSArray arrayWithObject:[[DataStore singleton] getHomeMenu]]; 

NSError *err;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj options:NSJSONWritingPrettyPrinted error:&err];

NSLog(@"JSON = %@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
但我得到的不是JSON,而是SIGABRT错误

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Menu)'
有没有办法解决这个问题,或者如何使实体类(分支、菜单等)与JSON序列化兼容

这是因为您的“Menu”类在JSON中不可序列化。基本上,这种语言不知道JSON应该如何表示对象(包括哪些字段,如何表示对其他对象的引用…)

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

  • 顶级对象是NSArray或NSDictionary
  • 所有对象都是NSString、NSNumber、NSArray、NSDictionary或NSNull的实例
  • 所有字典键都是NSString的实例
  • 数字不是NaN或无穷大
这意味着该语言知道如何序列化字典。因此,从菜单中获取JSON表示的一种简单方法是提供菜单实例的字典表示,然后将其序列化为JSON:

- (NSDictionary *)dictionaryFromMenu:(Menu)menu {
    [NSDictionary dictionaryWithObjectsAndKeys:[menu.dateUpdated description],@"dateUpdated",
    menu.categoryId, @"categoryId",
    //... add all the Menu properties you want to include here
    nil];
}
你可以这样使用它:

NSDictionary *menuDictionary = [self dictionaryFromMenu:[[DataStore singleton] getHomeMenu]]; 

NSError *err;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:menuDictionary options:NSJSONWritingPrettyPrinted error:&err];

NSLog(@"JSON = %@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);

NSJSONSerialization
上有一个类方法
isValidJSONObject
,它告诉您对象是否可以序列化。正如Julien指出的,您可能必须将对象转换为
NSDictionary
NSManagedModel
提供了一些方便的方法来获取实体的所有属性。因此,您可以为
NSManagedObject
创建一个类别,该类别具有将其转换为
NSDictionary
的方法。这样,您就不必为每个要转换为字典的实体编写
toDictionary
方法

@implementation NSManagedObject (JSON)

- (NSDictionary *)toDictionary
{
    NSArray *attributes = [[self.entity attributesByName] allKeys];
    NSDictionary *dict = [self dictionaryWithValuesForKeys:attributes];
    return dict;
}

您可以使用NSJSONSerialization类的+isValidJSONObject:method。如果无效,可以使用NSString的-initWithData:encoding:method

- (NSString *)prettyPrintedJson:(id)jsonObject
{
    NSData *jsonData;

    if ([NSJSONSerialization isValidJSONObject:jsonObject]) {
        NSError *error;
        jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject
                                                           options:NSJSONWritingPrettyPrinted
                                                             error:&error];

        if (error) {
            return nil;
        }
    } else {
        jsonData = jsonObject;
    }

    return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

我让人用以下值切换键:@{value:@“key”}
应该是{@“key”:value}

这对我帮助很大。谢谢非常感谢你。它就像一个符咒。这是我需要的完美解决方案。:)大家注意,如果没有这个问题,我们永远不会有这个伟大的答案,那么投票表决这个问题和答案如何?