您的位置:首页 > 理论基础 > 数据结构算法

IOS网络篇15之网络数据结构JSON XML

2014-10-22 11:32 519 查看
JSON数据格式是javascript的一个子集,语法如下:
(1){}:对象。以{开始,以}结束。
(2),每个对象之间用逗号隔开
(3):name\value之间用:表示。
(4)[]。多个对象放在一起用[]括起来。
(5)“”修饰字符串

JSON的最优框架是NSJSONSerialization。IOS5.0之后系统提供的。
提到数据交换格式首先应该考虑的是JSON,而不是Xml。因为JSON更加简单,效率更高。
增 删 改 查 都是对字典和数组来说的。因此以后都是对数组和字典的增删改查。
顶层对象必须是NSArray或者NSDictionary
所有的对象必须是NSString、NSNumber、NSArray、NSDictionary、NSNull的实例
所有NSDictionary的key必须是NSString类型
数字对象不能是非数值或无穷。

JSON与XML最大的不同在于XML是一个完整的标记语言,而JSON不是。这使得XML在程序判读上需要比较多的功夫。
目前常用的有4种json解析方法:NSJSONSerialization 、SBJson、JSONFramwork、TouchJSON。
其中第一个NSJSONSerialization是IOS在5.0之后自带的,而且效率相比较其它几种速度非常快,因此目前这种数据格式使用较多。



天气状况,网络请求。
string=今天是 2014年2月19日 星期三 北京 的天气状况是:晴转多云 5~-5
#pragmajson网络数据处理
-(void)Networkinit{

UIButton *button = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];
button.frame =
CGRectMake(100,
150,80,50);
[button
addTarget:selfaction:@selector(buttonaction:)forControlEvents:UIControlEventTouchUpInside];
[button
setTitle:@"NSJson"forState:UIControlStateNormal];
[self.viewaddSubview:button];

NSURL *url = [NSURLURLWithString:jsonSourceURLAddress_1];
NSURLRequest *urlrequest = [[NSURLRequestalloc]initWithURL:urlcachePolicy:NSURLRequestReloadIgnoringLocalCacheDatatimeoutInterval:30];
NSURLConnection *connect = [[NSURLConnectionalloc]initWithRequest:urlrequestdelegate:self];
[connect
start];
}
-(void)buttonaction:(UIButton*)buttonp{
NSError *error =
nil;
NSDictionary * rootDic = [NSJSONSerializationJSONObjectWithData:dataweatheroptions:NSJSONReadingMutableLeaveserror:&error];
NSDictionary *weatherInfo = [rootDic
objectForKey:@"weatherinfo"];
NSString *string =[NSStringstringWithFormat:@"今天是%@ %@ %@ 的天气状况是:%@ %@",[weatherInfoobjectForKey:@"date_y"],[weatherInfo
objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
NSLog(@"string=%@",string);
}
#pragmamark- NSURLConnectionDataDelegate methods
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
UIAlertView * alertV = [[UIAlertViewalloc]initWithTitle:@"网络连接失败"
message:[NSString stringWithFormat:@"%@",error] delegate:selfcancelButtonTitle:nilotherButtonTitles:nil,nil];
[alertV
show];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData *)data
{
dataweather = data;
stringweather = [[NSStringalloc]initWithData:dataencoding:NSUTF8StringEncoding];
}
JSon的读写操作,文件的构成。
{
"prise" : [
"5.8",
"6.6"
],
"苹果" : "苹果",
"香蕉" : "banana"
}
定义了一个集合,集合种有value key 所以有了"苹果" : "苹果",这种关系。
注意顶级目录只能用集合或者数组,子集合种也有一定的数据类型规定。
苹果=苹果
"\U82f9\U679c"="\U82f9\U679c";
实际解码之后直接就是字符串了。
deserializedDictionary={
prise= (
"5.8",
"6.6"
);
"\U82f9\U679c"= "\U82f9\U679c";
"\U9999\U8549"= banana;
}
16Jsonweather[2282:c07]苹果=苹果
16Jsonweather[2282:c07]价格=(
"5.8",
"6.6"
)
-(void)JsonWrite{
NSMutableDictionary*dictionary = [[NSMutableDictionaryalloc]init];
[dictionarysetValue:@"苹果"forKey:@"苹果"];
[dictionary
setValue:@"banana"forKey:@"香蕉"];
NSArray *array=[[NSArrayalloc]initWithObjects:@"5.8",@"6.6",nil];
[dictionary
setValue:array forKey:@"prise"];
NSError *error;
NSData *jsondata = [NSJSONSerializationdataWithJSONObject:dictionaryoptions:NSJSONWritingPrettyPrintederror:&error];
if (error){
NSLog(@"Jsoncreatfailed!");
}else{
NSLog(@"Jsoncreatsucessed!");
}
jsonpath = [NSHomeDirectory()stringByAppendingPathComponent:@"Document"];
BOOLwritesuccess = [jsondata
writeToFile:jsonpathatomically:YES];
if(writesuccess) {
NSLog(@"writesuccess!");
}else{
NSLog(@"writefailed!");
}

}
-(void)jsonread{
NSData *data = [[NSDataalloc]initWithContentsOfFile:jsonpath];
NSError *error;
id jsondata= [NSJSONSerializationJSONObjectWithData:dataoptions:NSJSONReadingAllowFragmentserror:&error];
if((error==nil)&&(jsondata!=nil)) {
if ([jsondata
isKindOfClass:[NSDictionary
class]]){
NSDictionary *deserializedDictionary = (NSDictionary *)jsondata;
NSLog(@"deserializedDictionary=%@",deserializedDictionary);
NSLog(@"苹果=%@",[deserializedDictionaryvalueForKey:@"苹果"]);
NSLog(@"价格=%@",[deserializedDictionaryvalueForKey:@"prise"]);
}else
if([jsondataisKindOfClass:[NSArrayclass]]){
NSArray *deserializedNSArray = (NSArray *)jsondata;
NSLog(@"deserializedNSArray=%@",deserializedNSArray);
NSLog(@"xx=%@",[deserializedNSArrayobjectAtIndex:0]);
}else{
NSLog(@"jsondata formis error!");
}
}
}
注意在JSON读取数据的时候,有一个option选项:

XML:数据格式
<?xml version="1.0"encoding="UTF-8"?> 1
<Notes> 2
<Noteid="1"> 3
<CDate>2012-12-21</CDate>
<Content>早上8点钟到公司</Content>
<UserID>tony</UserID>
</Note>
<Note
id="2">
<CDate>2012-12-22</CDate>
<Content>发布iOSBook1</Content>
<UserID>tony</UserID>
</Note>
</Notes>
(1)声明:制定xml的版本以及字符集。版本号1.0。字符集采用UTF-8.中文字符。
(2)根元素:根元素只有一对。<Notes>开始,</Notes>结束。
(3)属性:<Noteid="1"> 其中Note是一个元素,id=”1”
是元素的一个属性。Id是属性名,1是属性值。
(4)子元素:<CDate>
(5)命名空间和限定名。
<f:table
xmlns:f="http://www.w3school.com.cn/furniture"> 1
<f:name>AfricanCoffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
第一行命名空间(属性)。
f 限定名。

Xml文档操作主要包括两部分,一个是读、一个是写。解析方式有sax和dom两种。Sax是一种基于事件驱动型的解析模式,速度很快,但只能用于读取。Ios中提供的NSXML使用的就是sax框架。还有一种是dom型。Dom方式可以修改xml中的内容。
Sax模式速度快,dom模式必须要把所有的数据一次性全部加载到然后再解析,如果要想对xml数据进行修改那么必须要dom模式。

这里的demo是以nsxml,ios5.0之后系统提供的。
首先注册一个通知用于接收解析完成之后的数据。然后调用start方法启动xml解析。
#pragmamark xml本地解析
-(void)nsxmlinit{
[[NSNotificationCenter
defaultCenter]addObserver:selfselector:@selector(xmldataload:)name:@"xmlreloadNotification"object:nil];
[self
start];
}
-(void)start{
NSString *xmlpath = [[NSBundlemainBundle]pathForResource:@"Notes"ofType:@"xml"];
NSURL *xmlurl= [NSURLfileURLWithPath:xmlpath];
NSXMLParser *nsxmlsax = [[NSXMLParseralloc]initWithContentsOfURL:xmlurl];
nsxmlsax.delegate =
self;
[nsxmlsax
parse];
NSLog(@"xml parsefinish!");
}
解析完成之后进行通知处理。
#pragmamark -
处理通知
-(void)xmldataload:(NSNotification*)notification
{
NSMutableArray *resList = [notificationobject];
NSDictionary *xmldictionary = [resList
objectAtIndex:0];
NSString *contentxml = [xmldictionary
valueForKey:@"Content"];
NSLog(@"contentxml=%@",contentxml);

}

解析的时候常用到的方法。
注意这里整个解析过程使用的整体架构。
我们首先定义一个大的NSMutableArray.然后将解析的所有数据分组,每个元素的属性分为一个数组中的一个元素。数组中的每个元素用NSMutableDictionary来表示。
(1)parserDidStartDocument:(NSXMLParser *)parser
xml 开始解析的时候调用,一般用于创建一个动态的数组。
(2)- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError
xml 解析出错的时候调用,一般情况下,debug模式下才有效。
(3)- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
遇到开始标签的时候触发,注意,所有《》都是开始标签。
以这个为例:



除了第一行、最后一行不触发之外,剩下的所有行都触发。
didStartElement:第一个显示的字符串
namespaceURI:空间名
qualifiedName:限定名
attributes:字典属性集合。
下面每一个新的元素的id开始的时候,创建一个新的字典。
(4)- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString *)string
碰到中间有字符串的时候就触发。字符串写入在string中。
首先清空回车和空格,然后查看字符串的内容是不是有效的。如果是有效的然后才开始向下执行。通过比较开始标签,获取当前的字符串的内容属于那个部分中的。
NSMutableDictionary *dict = [_noteslastObject];
通过这个追加数组中最后一个数组元素:字典。中的内容。
(5)//遇到结束标签时候出发
- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName;

不解释,注意开始标签的时候清空。
(6)//遇到文档结束时候触发
- (void)parserDidEndDocument:(NSXMLParser *)parser
文档结束,发送通知,数组清空。

//文档开始的时候触发
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
_notes = [NSMutableArraynew];
}
//文档出错的时候触发
- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError
{
NSLog(@"%@",parseError);
}
//遇到一个开始标签时候触发
- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
_currentTagName = elementName;
if ([_currentTagNameisEqualToString:@"Note"]){
NSString *_id = [attributeDict
objectForKey:@"id"];
NSMutableDictionary *dict = [NSMutableDictionarynew];
[dict
setObject:_id forKey:@"id"];
[_notes
addObject:dict];
}
// NSLog(@"elementName=%@",elementName);
// NSLog(@"_notes=%@",_notes);

}
//遇到字符串时候触发
- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString *)string
{
//替换回车符和空格
string =[string
stringByTrimmingCharactersInSet:[NSCharacterSetwhitespaceAndNewlineCharacterSet]];
if ([stringisEqualToString:@""]) {
return;
}
NSMutableDictionary *dict = [_noteslastObject];
// NSLog(@"dict=%@",dict);
if ([_currentTagNameisEqualToString:@"CDate"]&& dict) {
[dict
setObject:string forKey:@"CDate"];
}
if ([_currentTagNameisEqualToString:@"Content"]&& dict) {
[dict
setObject:string forKey:@"Content"];
}

if ([_currentTagNameisEqualToString:@"UserID"]&& dict) {
[dict
setObject:string forKey:@"UserID"];
}
// NSLog(@"dict_after=%@",dict);
// NSLog(@"_notes_after=%@",_notes);
}
//遇到结束标签时候出发
- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName;
{
self.currentTagName=nil;
}
//遇到文档结束时候触发
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
[[NSNotificationCenter
defaultCenter]postNotificationName:@"xmlreloadNotification"object:self.notesuserInfo:nil];

self.notes =nil;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: