前言
实现思路
协议设定
补充
功能的优缺点分析
小结
前言
当我们处理接口数据的时候,有些情况仅仅需要获取一个或多个字段,来进行状态判断或数据显示。在写这部分代码的时候,或多或少会有一种重复感,但它又不是一成不变的重复,而是其模式相同,大量的字典取值操作,又或者多层的字典取值。这里能否实现一个功能,减少重复操作,一步到位,又或者提高下效率,让这部分代码逻辑变得简洁统一。我想可以自己定义一个取值协议,通过这个协议对数据进行解析,获取目的字段。这样就方便多了,只要根据协议解析就就可以省去很多重复操作。
实现思路
获取到后台数据的时候,接口回调回来的是一个字典对象,如果不是,那么需要进行一层处理转换成字典对象。然后,我们只需要对这个字典对象一层一层的解析,直到获取并返回目的字段的值。在解析的过程中,添加必要的健壮性处理,如果无法满足下一步解析的条件,结束解析并返回错误信息。
协议设定
传入特定结构的字符串作为解析的依据。而这个字符串的结构规则就是协议的内容。
1.把"{"作为字典类型的标记
2.把"["作为数组类型的标记
3.在"{"、"["前添加各自的字段名keyName
4.由左到右解析
例如:@"keyName0{KeyName1{dstKeyName{"
第一层字段名为keyName0,类型为字典,所以先解析出一个字典对象value0。通过value0和第二层字段名KeyName1,解析出一个value1。如此类推,通过value1获取目的字段dstKeyName的值dstValue。
其正确的数据结构:
{
"keyName0":{
"KeyName1":{
"dstKeyName":{
//keys & values
}
}
}
}
补充
能获取下一层的必须是一个字典对象,就是说协议字符串目的字段之前所有字段的类型标记都为"{"。还有一点,我们可以在目的字段后面添加类型标记,这样的话,就可以根据这个类型标记来判断目的字段的值的类型是否与期待的一致。可以添加NSString、NSNumber类型的符号如NSString对应@,Number对应$等,约定好添加逻辑处理即可。
测试代码:
NSString *path = [[NSBundle mainBundle]pathForResource:@"json" ofType:@"txt"];
NSString *jsonString = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *jsonError = nil;
NSDictionary *testDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonError];
if (jsonError) {
NSLog(@"error0:%@ ",jsonError);
return;
}
NSNumber *status = [SafeDataProcessor getObjectWithFormmateString:@"data{status" data:testDictionary];
//直接获取page字段
NSNumber *page = [SafeDataProcessor getObjectWithFormmateString:@"data{result{all_page" data:testDictionary];
//先获取result字段,再获取list字段
NSDictionary *result = [SafeDataProcessor getObjectWithFormmateString:@"data{result{" data:testDictionary];
NSArray *list = [SafeDataProcessor getObjectWithFormmateString:@"list[" data:result];
NSLog(@"\n statu:%@,\n page:%@,\n list:%@,\n result:%@,\n ",status,page,list,result);
调试结果:
2018-02-22 10:57:25.093365+0800 SafeNetDataProcessor[2882:123596]
statu:200,
page:20,
list:(
{
"check_reply_info" = {
num = 6;
type = 1;
};
content = "\U5b66\U4e60\U4e0d\U662f\U7ed9\U8001\U5e08\U5b66\U7684\Uff0c\U662f\U7ed9\U4f60\U81ea\U5df1\U5b66\U7684\U3002";
"create_time" = 1518361773;
floor = 1;
groupid = "-1";
"light_count" = 1992;
pid = 259696;
puid = 25941704;
quote = (
);
"quote_deleted" = 0;
smallcontent = "\U5b66\U4e60\U4e0d\U662f\U7ed9...";
time = "8\U5c0f\U65f6\U524d";
togglecontent = "";
"update_info" = 0;
userImg = "http://i1.hoopchina.com.cn/user/665/256623943989665/256623943989665-1518360162.jpeg@45h_45w_2e";
userName = "\U4e8c\U53f7\U8001\U6d41\U6c13";
"user_banned" = 0;
via = 9;
},
功能的优缺点分析
优点:这个功能的优点很明显,就是把分散的处理集中了,输入结构字符串和网络返回值,即可获取目的字段的值,中间的健壮性处理和取值操作都可以省掉了,从这个角度看,减少了编码工作,提高了效率;同时,统一的健壮性处理,只要保证内部处理正确稳定,那么该部分处理就是稳定安全的。对比原来,每次都要手写一次,难保每次都是正确的,特别拷贝大段代码进行修改,这样的操作容易出现低级错误。
缺点:根据字符串来解析,所以会有额外的字符串操作处理,使程序的执行效率变低。
小结
从程序运行的角度来看,效率最高的的固然是最贴近需求,无多余操作的代码。但从软件开发的角度来看,程序本身执行效率很重要,但是程序健壮性、编码效率和编码质量也同样重要。
demo地址:
https://github.com/zmubai/SafeDataProcessor
end~