我正在尝试将我自己的对象集合深层解析为NSDictionary(对于JSON)。
我有一个基础对象类,我的模型的 所有 扩展,而这个基础对象又扩展了NSObject:
@interface BaseObj : NSObject <DICTMaker>
- (NSMutableDictionary *) toDICT;
@end
在方法中,我使用objc-runtime来获取属性列表。我可以获得使用[self valueForKey:]
的任何属性,我继续向我的字典中插入属性的名称和值。
但是,到目前为止我注意到的是NSNumber
和用户定义的类没有添加到字典中!我的解析器最确定地识别它们,因为我把它全部吐出到日志中;但[self valueForKey:]
会在所有nil
和用户定义的对象上返回NSNumbers
。
- (NSMutableDictionary *)toDICT {
NSMutableDictionary *props = [NSMutableDictionary dictionary];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
// Both of these work, I promise:
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
NSString *propertyType = [NSString stringWithUTF8String:getPropertyType(property)];
NSLog( @"%@ of Type: %@", propertyName, propertyType );
id propertyValue = [self valueForKey:propertyName];
if ( [ propertyValue respondsToSelector:@selector(toDICT:) ] )
[ props setObject:[propertyValue toDICT] forKey:propertyName ];
else if ( propertyValue )
[ props setObject:propertyValue forKey:propertyName ];
else
NSLog( @"Unable to get ref to: %@", propertyName );
}
free(properties);
return props;
}
以下是我向创作者投掷的示例对象:
@interface UserRegistrationLocation : BaseObj {
NSString *address, *street, *street_2, *city;
NSNumber *addr_state, *addr_zip;
}
@interface UserRegistrationContact : BaseObj {
NSString *first_name, *last_name;
NSString *p_phone_area, *p_phone_first_3, *p_phone_last_4;
NSString *s_phone_area, *s_phone_first_3, *s_phone_last_4;
}
@interface UserRegistration : BaseObj {
NSString *email, *password, *password_confirm;
NSNumber *referral;
UserRegistrationContact *primary, *secondary;
UserRegistrationLocation *address;
}
NSMutableDictionary *mydict = [myUserRegistration toDICT];
生成的字典仅包含电子邮件,密码和password_confirm的条目:
[11012:f803] Unable to get ref to: referral
[11012:f803] Unable to get ref to: primary
[11012:f803] Unable to get ref to: secondary
[11012:f803] Unable to get ref to: address
[11012:f803] {"user":{"password":"haxme123","password_confirm":"haxme123","email":"my@email.com"}}
请帮助=}!
答案 0 :(得分:2)
您只为值而非属性声明了ivars。 class_copyPropertyList
需要@property
声明。您可以使用ivar访问class_getInstanceVariable
等功能。
然而,我认为这种方法试图有点过于聪明。我将实现一个返回序列化键的方法,例如-(NSArray *)keysForJSONSerialization
。这样可以更清楚地揭示意图,并允许您阻止某些属性的序列化(我怀疑您在某些时候会想要)。
答案 1 :(得分:1)
也许我明白这个问题是错的,但是你的推荐,主要的,所以不仅仅是null? 如果它们不在keyvalue存储区中,您将获得异常。 如果在keyvalue存储中找到属性但指定了nil,则只调用其他部分。至少从您的示例代码中,无法确定是否设置了值。
如果我将您的示例缩减为以下代码,我会得到以下输出 测试值:(null) 无法获得参考:测试 aNumber with Value:5
test为null,会给你的消息“无法......”。 aNumber是正确的。如果我将测试更改为某些文本,则“无法...”部分会消失。此处不会出现非属性的附加成员变量_noProp,因为copyPropertyList仅复制属性。
@interface TestValueForKey : NSObject {
NSString* _test;
NSString* _noProp;
NSNumber* _aNumber;
}
@property (retain) NSString* test;
@property (retain) NSNumber* aNumber;
-(void)myTest;
@implementation TestValueForKey
@synthesize test = _test;
@synthesize aNumber = _aNumber;
-(id)init
{
if( (self = [super init]) != nil) {
_test = nil;
_aNumber = [NSNumber numberWithInt:5];
}
return self;
}
-(void)myTest
{
NSMutableDictionary *props = [NSMutableDictionary dictionary];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for( i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
// Both of these work, I promise:
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
id propertyValue = [self valueForKey:propertyName];
NSLog( @"%@ with Value: %@", propertyName, propertyValue );
if ( propertyValue )
[ props setObject:propertyValue forKey:propertyName ];
else
NSLog( @"Unable to get ref to: %@", propertyName );
}
free(properties);
}
@end