项目需要将json格式的字符串转换成易于维护的model类,也找过别人写的,大致思想都是遍历model来实现,逻辑很复杂,也耗性能!
以前的实现是将json遍历,所以将以前在android上写的一段翻译成oc!代码如下:
//
// HsBaseEntity+entity.h
// JsonToEntity
//
// Created by 王金东 on 15/1/1.
// Copyright (c) 2015年 王金东. All rights reserved.
//
#import "HsBaseEntity.h"
@interface HsBaseEntity (entity)
+ (id)objectWithData:(id)data;
@end
//
// HsBaseEntity+entity.m
// JsonToEntity
//
// Created by 王金东 on 15/1/1.
// Copyright (c) 2015年 王金东. All rights reserved.
//
#import "HsBaseEntity+entity.h"
#import <objc/runtime.h>
@implementation HsBaseEntity (entity)
+ (id)objectWithData:(id)data{
if([data isKindOfClass:[NSDictionary class]]){
return [self dictionaryToEntity:data];
}else if([data isKindOfClass:[NSArray class]]){
return [self arrayToEntity:data];
}
return nil;
}
+ (instancetype)dictionaryToEntity:(NSDictionary *)dictionary{
id model = [[self alloc] init];
return [model transformDictionaryToEntity:dictionary];
}
+ (NSMutableArray *)arrayToEntity:(NSArray *)array{
NSMutableArray *entityArray = [NSMutableArray arrayWithCapacity:array.count];
for (NSDictionary *dictionary in array) {
id model = [[self alloc] init];
[entityArray addObject:[model transformDictionaryToEntity:dictionary]];
}
return entityArray;
}
- (instancetype)transformDictionaryToEntity:(NSDictionary *)dictionary{
NSEnumerator *enumerator = [dictionary keyEnumerator];
NSString *key;
while ((key = [enumerator nextObject])) {
id value = dictionary[key];
if ([value isKindOfClass:[NSNull class]]) {
continue;
}
if([value isKindOfClass:[NSArray class]]){//判断该属性的值是不是数组
Class objectClass = nil;
if([self exsitWithKey:key]){//判断key是否存在
//处理key
NSString *keyArray = [key stringByReplacingOccurrencesOfString:self.arraySuffix withString:@""];
NSString *firstLetterCap=[[keyArray substringToIndex:1] capitalizedString];
NSString *modelKeyArray=[keyArray stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:firstLetterCap];
objectClass = NSClassFromString(modelKeyArray);
if (objectClass) {
NSString *message = [NSString stringWithFormat:@"%@不是HsBaseEntity的子类",modelKeyArray];
NSAssert([objectClass isSubclassOfClass:[HsBaseEntity class]], message);
value = [objectClass arrayToEntity:value];
}
}
if (objectClass == nil && [self respondsToSelector:NSSelectorFromString(@"objectClassInArray")]){
//处理数组里面有模型的情况
NSDictionary *objectClassDic = [self performSelector:NSSelectorFromString(@"objectClassInArray")];
if(objectClassDic)
objectClass = objectClassDic[key];
if (objectClass)
value = [objectClass arrayToEntity:value];
}
}else if ([value isKindOfClass:[NSDictionary class]]) {//判断该属性是否是自定义对象
Class keyClass = [self classWithKey:key];
value = [keyClass dictionaryToEntity:value];
}
[self setValue:value forKey:key];
}
return self;
}
//判断是否存在
- (BOOL)exsitWithKey:(NSString *)key{
const char *charKey = [[NSString stringWithFormat:@"_%@",key] UTF8String];
Ivar ivar = class_getInstanceVariable([self class],charKey);
if(ivar != nil){
return YES;
}
return NO;
}
//根据key获取字段类型
- (Class)classWithKey:(NSString *)key{
const char *charKey = [[NSString stringWithFormat:@"_%@",key] UTF8String];
Ivar ivar = class_getInstanceVariable([self class],charKey);
NSString *code = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
// 去掉@"和",截取中间的类型名称
code = [code substringFromIndex:2];
code = [code substringToIndex:code.length - 1];
return NSClassFromString(code);
}
@end
顺便贴上HsBaseEntity类的代码:
//
// HsBaseEntity.h
//
//
// Created by 123 on 14-6-13.
// Copyright (c) 2014年 chenjiong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface HsBaseEntity : NSObject
@property (nonatomic,strong) NSString *arraySuffix;
- (NSDictionary *)objectClassInArray;
@end
//
// HsBaseEntity.m
//
//
// Created by 123 on 14-6-13.
// Copyright (c) 2014年 chenjiong. All rights reserved.
//
#import "HsBaseEntity.h"
@implementation HsBaseEntity
- (instancetype)init{
self = [super init];
if (self) {
//建议统一后缀
self.arraySuffix = @"Array";
//如果后缀不同意,变量前缀是一个不存在的对象 则建议使用objectClassInArray方法,自己用映射
}
return self;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"undefinedKey:%@",key);
}
- (NSDictionary *)objectClassInArray{
return nil;
}
@end