博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS JSON、XML解析技巧
阅读量:6215 次
发布时间:2019-06-21

本文共 7078 字,大约阅读时间需要 23 分钟。

序言:

以下实验效果会采用简单的方式呈现,读者可根据自身情况修改实验代码

#####一、JSON解析 这里,我们需要先分析数据再做解析操作!

1.准备的数据:在Safari浏览器访问https://www.crios.cn/test.json 2.效果图如下

打开xcode->新建项目->新建Person模型装载json数据

// 代码如下// 以下代码意义是根据数据来创建变量的#import 
@interface Person : NSObject@property (copy, nonatomic) NSString *username;@property (strong, nonatomic) NSNumber *age;@property (strong, nonatomic) NSNumber *id;@end复制代码

回到ViewContorller.m文件,添加以下代码

/* 在头部导入Person类// Model#import "Person.h"*/    // 1.创建url    NSURL *url = [NSURL URLWithString:@"https://www.crios.cn/test.json"];        // 2.创建请求    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0];        // 3.创建NSURLSession    NSURLSession *session = [NSURLSession sharedSession];        // 4.创建NSURLSessionDataTask    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        if (!error) {                        NSArray *jsons = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];                        NSMutableArray *results = [NSMutableArray array];            for (NSDictionary *dic in jsons) {                Person *person = [[Person alloc] init];                [person setValuesForKeysWithDictionary:dic];                [results addObject:person];            }            NSLog(@"结果:%@", results);                    } else {            NSLog(@"错误提示:%@",error);        }    }];        // 5.开启任务(如果任务在挂起状态,这里会重新开启任务)    [dataTask resume];复制代码

setValuesForKeysWithDictionary意义:     dic中的key会找Person类中的变量,一一对应,再将key对应的value赋值过去

打印效果:

上面无法打印模型的变量值,我们可在Person.m文件中添加以下代码:

- (NSString *)description {        return [NSString stringWithFormat:@"<%@:%p>{id:%@,name:%@,age:%@}",self.class,self,_id, _username, _age];    }复制代码

输出效果

#####第一问,我们已设定好Person类中的变量,但我们定义好的Person类与服务器返回的数据不一致会出现何种情况,此时怎么办?

程序直接奔溃

莫慌,直接在Person.m文件中添加如下代码

// 代码块暂时不需要其他操作,可空着- (void)setValue:(id)value forUndefinedKey:(NSString *)key {    }复制代码

程序正常跑起来了。 #####接着来,第二问,服务器返回的数据,有我们OC语言的关键字,赋值操作会出现一些无法预测的问题,这可咋办呢?

解决这个问题首先先在Person.h文件中修改代码

@property (copy, nonatomic) NSString *username;//@property (strong, nonatomic) NSNumber *age;// 将关键字修改成我们想要的模样@property (strong, nonatomic) NSNumber *ID;复制代码

其次在Person.m文件中添加如下代码

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {        if ([key isEqualToString:@"id"]) {        self.ID = value;    }    }复制代码

实验效果跟预期一样。成功了。?

#####第三问,我们打印的数组中,出现的中文为乱码,这可咋办呢?

新建NSArray Category

在NSArray+Log.m文件中添加以下代码

// 实际代码看这里,以下代码意义不解释,相信大家都看得懂- (NSString *)descriptionWithLocale:(id)locale {    NSMutableString *resultStr = [NSMutableString stringWithString:@"??(\n"];    [self enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {        [resultStr appendFormat:@"\t%@\n",obj];    }];    [resultStr appendFormat:@")\n"];    return resultStr;}复制代码

结果输出:

#####二、XML解析 XML:     XML是一种可扩展"标记"语言,特点是阅读方便,美观大方。     解析方式:

方式 介绍 特点
DOM MAC提供的解析方法,iOS中无法直接使用 1.内存开销大
2.可读可写
3.将数据以树形结构加载到内存
SAX 适用于iOS的解析方式 1.内存开销小
2.只读
3.速度快
4.从上到下,顺序解析的过程

行,我们来做实验。 1)同样的,我们也需要分析数据再做解析操作!

1.准备的数据:在谷歌浏览器访问http://www.crios.cn/persons.xml (数据也可从其他地方来,道理是一样的) 2.效果图如下

2)新建Person类,来装载数据,看了前面的json解析之后,这里会更容易明白。

Person.h文件

@property (strong, nonatomic)NSNumber *personId;@property (copy, nonatomic)NSString *height;@property (copy, nonatomic)NSString *age;@property (copy, nonatomic)NSString  *name;@property (copy, nonatomic)NSString  *sex;@property (copy, nonatomic)NSString  *desc;复制代码

Person.m文件

- (NSString *)description {        return [NSString stringWithFormat:@"<%@:%p>{videoID:%@,name:%@,age:%@,height:%@,sex:%@,desc:%@}",[self class],self,self.personId,self.name,self.age,self.height,self.sex,self.desc];    }- (void)setValue:(id)value forUndefinedKey:(NSString *)key {      // 这里代码可空着,主要意义是防止服务器返回的数据与我们创建的Model类对应不上}复制代码

4)ViewController.m文件

// 1.导入Person 类#import "Person.h"// 2.遵守代理协议@interface ViewController ()
// 3.创建可变数组@property (strong, nonatomic) NSMutableArray *persons;// 4.创建可变字符串@property (strong , nonatomic) NSMutableString *elementStr;// 5.当前解析的节点模型@property (strong, nonatomic) Person *currentPerson;@end@implementation ViewController// MARK: 懒加载- (NSMutableArray *)persons { if (!_ persons) { _ persons = [[NSMutableArray alloc] init]; } return _ persons;}- (NSMutableString *)elementStr { if (!_elementStr) { _elementStr = [[NSMutableString alloc] init]; } return _elementStr;}@end复制代码
  1. 请求数据
//1.url    NSURL *url = [NSURL URLWithString:@"http://www.crios.cn/persons.xml"];        // 2.创建请求    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0];        // 3.创建NSURLSession    NSURLSession *session = [NSURLSession sharedSession];        // 4.创建NSURLSessionDataTask    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        if (!error) {                        // XML解析            NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data];                    // 设置代理            xmlParser.delegate = self;                    //解析器解析            [xmlParser parse];        }    }];        // 5.开启任务(如果任务在挂起状态,这里会重新开启任务)    [dataTask resume];复制代码

3)补充说明这里采用苹果原生NSXMLParser类来进行解析,主要通过6种代理方法来进行操作

// 1.打开文档- (void)parserDidStartDocument:(NSXMLParser *)parser {    NSLog(@"1.开始文档");        //1.清空数组    [self.persons removeAllObjects];}// 2.开始节点- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary
*)attributeDict { if ([elementName isEqualToString:@"person"]) { //1.新建模型 self.currentPerson = [[Person alloc] init]; //2设置personID的属性 self.currentPerson.personId = @([attributeDict[@"personId"] intValue]); }}// 3.发现节点内容- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { [self.elementStr appendString:string];}// 4.结束节点- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if ([elementName isEqualToString:@"person"]) { [self.persons addObject:self.currentPerson]; } else if (![elementName isEqualToString:@"persons"]) { [self.currentPerson setValue:self.elementStr forKey:elementName]; } //清空字符串 [self.elementStr setString:@""];}// 5.结束解析- (void)parserDidEndDocument:(NSXMLParser *)parser { NSLog(@"结果:%@",self.persons);}// 6.错误处理- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { NSLog(@"错误描述:%@",parseError.description);}复制代码

#####总结: #####    实验结束,解析JSON这里为了便捷展示采用苹果原生NSJSONSerialization类解析。简单粗暴。 #####    网络请求不用老方法:NSURLConnection中的 sendAsynchronousRequest,直接采用NSURLSession。 #####    最后,模型的赋值可采用Runtime机制,效率会更高,这里不多讲,后面会专门写Runtime文章

转载于:https://juejin.im/post/5b0e69f9518825157914ffa3

你可能感兴趣的文章
乘飞机不仅能玩手机 Wifi速度还快上天
查看>>
一种新型的获取威胁情报手段:窃听黑客
查看>>
专访陈士凯:机器人已经不需要讲故事了丨CCF-GAIR 2017
查看>>
《Hadoop实战第2版》——1.8节本章小结
查看>>
《 自动化测试最佳实践:来自全球的经典自动化测试案例解析》一一1.4 利用验收测试驱动开发,使用FitNesse测试GUI...
查看>>
《HTML 5+CSS 3入门经典》——第2章 去其糟粕,取其精华——HTML 5 的元素与属性...
查看>>
云存储服务是否是正确选择?
查看>>
witter被Instagram超越,在中国超越微博的将是谁
查看>>
云服务互联网企业使用率最高
查看>>
《代码之殇》(原书第2版)——第2章 过程改进,没有灵丹妙药 2004年10月1日...
查看>>
写给运营商的三个锦囊
查看>>
其他类安防生产型上市企业2015年经营情况
查看>>
上汽集团结盟传感器制造商Savari
查看>>
喜欢吗?微软公布新版Win10开始菜单:致敬Win8
查看>>
华芯投资40亿现金收购美芯片测试设备厂商Xcerra
查看>>
程序员当选全球轮值总裁 WiFi万能钥匙誓做中国“最科技”
查看>>
光伏电站美的三层境界
查看>>
Spring MVC学习笔记之Hello World
查看>>
Google的排名优化需要注意哪些方面的细节?
查看>>
《Android的设计与实现:卷I》——第2章 2.6JNI异常处理
查看>>