如何使用JSON在NSDictionary中序列化自定义对象?

时间:2012-06-04 05:53:16

标签: ios5 nsdictionary nsjsonserialization custom-object

我有以下代码:

NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"one", @"oneKey", 
@"two", @"twoKey", customObject, @"customObjectKey", nil];
if([NSJSONSerialization isValidJSONObject:dict])
{
    NSLog(@"Went through.");
}

如果对象是NSString,它将会通过,但是一旦我将customObject添加到字典中,它就不再有效了。我该如何解决这个问题?任何帮助深表感谢。提前谢谢!

6 个答案:

答案 0 :(得分:4)

简单的事实是:你做不到。阅读NSJSONSerialization的文档,该文档未列出NSCoding。 :(

答案 1 :(得分:1)

您无法将自定义对象设置为Dictionary的键。确保你的密钥是NSStrings

来自func +(BOOL)的Foundatoin.framework的文本isValidJSONObject:(id)obj;

- All dictionary keys are NSStrings

答案 2 :(得分:1)

原因:这是因为" customObject"不是:NSArray,NSDictionary和NSString。最有可能是用户定义的类,这是isValidJSONOperation的合同:

/* Returns YES if the given object can be converted to JSON data, NO otherwise. The object must have the following properties:
    - Top level object is an NSArray or NSDictionary
    - All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
    - All dictionary keys are NSStrings
    - NSNumbers are not NaN or infinity
 Other rules may apply. Calling this method or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.
 */
+ (BOOL)isValidJSONObject:(id)obj;

可能的解决方案1:在您的customObject类中添加另一个NSDictonary类型的属性,该属性由示例字典调用,该属性包含要在JSON中添加的属性。

NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"one", @"oneKey", 
@"two", @"twoKey", customObject.dictionary, @"customObjectKey", nil];

可能的解决方案2:使用要从customObject添加到JSON中的属性(和值)创建一个新字典。

答案 3 :(得分:0)

键是字符串,但值可以是任何对象,包括NSNull。

答案 4 :(得分:-1)

“如何在XCode中使用JSON在NSDictionary中序列化自定义对象?”

说明我厌恶XCode的另一个原因,并希望有人会在20世纪90年代拖延它。

让我们来看看我们如何序列化自定义对象。

假设您有一个非常简单的UserRecord类,其中包含.h文件:

@interface UserRecord : NSObject

@property(nonatomic) int UserID;
@property(nonatomic, strong) NSString* FirstName;
@property(nonatomic, strong) NSString* LastName;
@property(nonatomic) int Age;

@end

这样的.m:

@implementation UserRecord

@synthesize UserID;
@synthesize FirstName;
@synthesize LastName;
@synthesize Age;

@end

如果您尝试创建UserRecord对象,并使用NSJSONSerialization类对其进行序列化..

UserRecord* sampleRecord = [[UserRecord alloc] init];
sampleRecord.UserID = 13;
sampleRecord.FirstName = @"Mike";
sampleRecord.LastName = @"Gledhill";
sampleRecord.Age = 82;

NSError* error = nil;
NSData* jsonData2 = [NSJSONSerialization dataWithJSONObject:sampleRecord options:NSJSONWritingPrettyPrinted error:&error];

..它会嘲笑你,抛出异常并使你的应用程序崩溃:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'

解决这个闹剧的一种方法是向NSObject添加一项功能,将您的数据转换为NSDictionary,然后序列化

这是我班级的新.m文件:

@implementation UserRecord

@synthesize UserID;
@synthesize FirstName;
@synthesize LastName;
@synthesize Age;

-(NSDictionary*)fetchInDictionaryForm
{
    NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];

    [dict setObject:[NSNumber numberWithInt:UserID] forKey:@"UserID"];
    [dict setObject:FirstName forKey:@"FirstName"];
    [dict setObject:LastName forKey:@"LastName"];
    [dict setObject:[NSNumber numberWithInt:Age] forKey:@"Age"];

    return dict;
}

@end

实际上,如果您愿意,可以一次性创建NSDictionary值:

-(NSDictionary*)fetchInDictionaryForm
{
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithInt:UserID], @"UserID",
                         FirstName, @"FirstName",
                         LastName,@"LastName",
                         [NSNumber numberWithInt:Age], @"Age",
                         nil];
    return dict;
}

完成此操作后,您可以获取NSJSONSerialization序列化您对象的NSDictionary版本:

UserRecord* sampleRecord = [[UserRecord alloc] init];
sampleRecord.UserID = 13;
sampleRecord.FirstName = @"Mike";
sampleRecord.LastName = @"Gledhill";
sampleRecord.Age = 82;


NSDictionary* dictionary = [sampleRecord fetchInDictionaryForm];
if ([NSJSONSerialization isValidJSONObject:dictionary])
{
    NSError* error = nil;
    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];
    NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    NSLog(@"%@", jsonString);
}

这将产生我们想要的JSON输出:

{
  "UserID" : 13,
  "FirstName" : "Mike",
  "LastName" : "Gledhill",
  "Age" : 82
}

令人震惊。即使在2015年,Apple的SDK也无法将一组简单的intNSString序列化为JSON。

希望这有助于其他XCode受害者。

答案 5 :(得分:-6)

您需要使用NSCoding协议来序列化自定义对象。

在.h文件中实现NSCoding协议,并在自定义类的.m文件中实现以下方法。

- (id)initWithCoder:(NSCoder *)aDecoder
{
   if(self = [super init]) // this needs to be [super initWithCoder:aDecoder] if the superclass implements NSCoding
   {
      aString = [[aDecoder decodeObjectForKey:@"aStringkey"] retain];
      anotherString = [[aDecoder decodeObjectForKey:@"anotherStringkey"] retain];
   }
   return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
   // add [super encodeWithCoder:encoder] if the superclass implements NSCoding
   [encoder encodeObject:aString forKey:@"aStringkey"];
   [encoder encodeObject:anotherString forKey:@"anotherStringkey"];
}