iOS 字典转模型

一、系统自带的json转换为字典
系统自带的转化主要使用NSJSONSerialization类来完成;json格式字符串转字典使用JSONObjectWithData:option:error函数来转换;字典转json格式字符串使用dataWithJSONObject:option:error

/*!
* @brief 把格式化的JSON格式的字符串转换成字典
* @param jsonString JSON格式的字符串
* @return 返回字典
*/
json格式字符串转字典:
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {
    if (jsonString == nil) {
    return nil;
    }

    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

    NSError *err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];

  if(err) {
    NSLog(@"json解析失败:%@",err);
    return nil;
  }
 return dic;

}

字典转json格式字符串:

+ (NSString*)dictionaryToJson:(NSDictionary *)dic
{

NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];

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

}

NSJSONWritingPrettyPrinted  是有换位符的。

如果NSJSONWritingPrettyPrinted 是nil 的话 返回的数据是没有 换位符的  

二、关于这个知识点,并没有太多难点,其中主要要记住的就是字典转模型,字典转模型一般步骤如下:
(1)首先创建一个模型类,创建需要数据的 get 和 set 方法,由编译器合成
例如:

@property (nonatomic, copy) NSString *answer; 
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *icon;

(2)在一个类中(假设为 MJQuestion)创建两个方法(一个类方法、一个对象方法,作用是一样的),传入 一个字典,取出数据用 get 方法保存到成员变量中,例如:

- (instancetype)initWithDict:(NSDictionary *)dict 
{
   if(self = [super init])
{
  //1、KVC版本
  //[self setValue:dict[@"icon"] forKeyPath:@"icon"];
  //[self setValue:dict[@"answer"] forKeyPath:@"answer"];
  //[self setValue:dict[@"options"] forKeyPath:@"options"];

  //2、属性
   self.icon = dict[@"icon"]; 
   self.answer = dict[@"answer"];
   self.options = dict[@"options"];

 //3、setValuesForKeysWithDictionary
 //[self setValuesForKeysWithDictionary:dict];
}
  return self; 
}

+ (instancetype)questionWithDict:(NSDictionary *)dict
 {
    return [[self alloc] initWithDict:dict]; 
 }

(3)如果将 plist 文件中的数据转成字典,并传给上面方法,返回值为 MJQuestion 对象,再将对象保存到 NSMutableArray 中,之后读取数据时就可以根据 NSMutableArray 索引取出每个 MJQuestion 对象,再从 MJQuestion 对象中读取数据显示到相关控件上。如果是服务器传来的字典,转成模型也类似

部分代码如下:

- (NSArray *)questions
{
if (_questions == nil)
{
   // 1.加载 plist 
   NSArray *dictArray =
[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"questions" ofType:@"plist"]];

  // 2.字典转模型
NSMutableArray *questionArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray)
{
  MJQuestion *question = [MJQuestion questionWithDict:dict];
  [questionArray addObject:question]; 
}

 // 3.赋值
 _questions = questionArray;

}

return _questions;
}

三、runtime给OC动态性的提供强大的支持,下面列举了利用runtime实现字典模型的转换

//字典转模型
-(instancetype)initWithDictionary:(NSDictionary *)dictionary{

    self = [super init];
    if (self) {

        for (NSString *key in dictionary.allKeys) {
            id value = dictionary[key];

            SEL  setter = [self propertySetterByKey:key];
            if (setter) {
                ((void (*)(id, SEL, id))objc_msgSend)(self, setter, value);
            }
        }
    }
    return  self;
}


//模型转字典
-(NSDictionary *)covertToDictionary{

    unsigned int count = 0;
    objc_property_t *properties = class_copyPropertyList([self class], &count);

    if (count != 0 ) {

        NSMutableDictionary *result = [@{} mutableCopy];

        for (NSUInteger i = 0; i < count; i ++) {
            const void *propertyName = property_getName(properties[i]);
            NSString *name = [NSString stringWithUTF8String:propertyName];

            SEL getter = [self propertyGetterBykey:name];
            if (getter) {
               id value = ((id (*)(id, SEL))objc_msgSend)(self, getter);
               if(value){
                   result[name] = value;
               }else{
                   result[name] = @"字典的key对应的value不能为nil哦!";
               }

            }
        }
        free(properties);

        return result;
    }

    free(properties);

    return nil;


}




#pragma mark - private method

//生成setter方法
-(SEL)propertySetterByKey:(NSString *)key{

    //设置方法的setS...大写
    NSString *propertySetterName = [NSString stringWithFormat:@"set%@:",key.capitalizedString];

    SEL setter = NSSelectorFromString(propertySetterName);
    if ([self respondsToSelector:setter]) {
        return setter;
    }

    return nil;

}


//生成getter方法

-(SEL)propertyGetterBykey:(NSString *)key{

    SEL getter = NSSelectorFromString(key);
    if ([self respondsToSelector:getter]) {
        return getter;
    }
    return nil;

}

字典转模型的实现:https://github.com/onebutterflyW/DictionaryConvertModel
runtime的实现:https://github.com/onebutterflyW/runtime

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员的修养

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值