1

我正在尝试将我自己的对象集合深度解析为 NSDictionary(用于 JSON)。

我有一个基础对象类,我的所有模型都扩展了它,而这个基础对象又扩展了 NSObject:

@interface BaseObj : NSObject <DICTMaker>
    - (NSMutableDictionary *) toDICT;
@end

在该方法中,我使用 objc-runtime 来获取属性列表。任何可以引用 using 的属性,我都会[self valueForKey:]将属性的名称和值插入到我的字典中。

但是,到目前为止我注意到的是NSNumbers 和用户定义的类没有添加到字典中!我的解析器最有把握地识别它们,因为我让它把所有东西都吐到日志中;但[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];

生成的字典仅包含 email、password 和 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"}}

请提供任何帮助=}!

4

2 回答 2

2

您只为值声明了 ivars,而不是属性。class_copyPropertyList需要@property声明。您可以使用 ivar 访问函数,例如class_getInstanceVariable.

但是,我认为这种方法有点太聪明了。我将实现一个方法,该方法返回要序列化的键数组,例如-(NSArray *)keysForJSONSerialization. 这将更清楚地揭示意图,并允许您防止某些属性的序列化(我怀疑您在某些时候会想要)。

于 2012-06-11T14:41:41.413 回答
1

也许我理解错了问题,但是您的推荐、主要等不只是空吗?如果它们不在键值存储中,你会得到一个异常。如果在键值存储中找到该属性但分配了 nil,则仅调用 else 部分。至少从您的示例代码中,无法确定是否设置了值。

如果我将您的示例简化为下面的代码,我会得到以下带有值的输出测试:(null) Unable to get ref to: test aNumber with Value: 5

test 为空,并且会给您的消息“无法...”。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
于 2012-06-11T19:27:28.637 回答