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

时间:2012-03-27 15:58:28

标签: iphone objective-c json serialization ios5

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

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

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

enter image description here

我正在尝试在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序列化兼容?

4 个答案:

答案 0 :(得分:81)

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

来自NSJSONSerialization Class Reference

  

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

     
      
  • 顶级对象是NSArray或NSDictionary。
  •   
  • 所有对象都是NSString,NSNumber,NSArray,NSDictionary或NSNull的实例。
  •   
  • 所有字典键都是NSString的实例。
  •   
  • 数字不是NaN或无穷大。
  •   

这意味着该语言知道如何序列化词典。因此,从菜单中获取JSON表示的一种简单方法是提供Menu实例的Dictionary表示,然后将序列化为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]);

答案 1 :(得分:24)

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

@implementation NSManagedObject (JSON)

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

答案 2 :(得分:1)

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

- (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];
}

答案 3 :(得分:0)

我将键切换为值:@ {value:@" key"} 它应该是@ {@" key":value}