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

本文介绍了iOS中网络数据结构,重点关注JSON和XML的区别。强调JSON因其简洁高效,通常优于XML作为数据交换格式。文中详细阐述了JSON的语法,并展示了如何使用NSJSONSerialization进行解析和序列化。同时,提供了XML的基本结构和解析方法,讨论了SAX和DOM解析模式。通过示例代码,演示了如何在iOS中进行XML解析。
摘要由CSDN通过智能技术生成

JSON数据格式是javascript的一个子集,语法如下:

(1){}:对象。以{开始,以}结束。

(2),每个对象之间用逗号隔开

(3):name\value之间用:表示。

(4)[]。多个对象放在一起用[]括起来。

(5)“”修饰字符串

 

JSON的最优框架是NSJSONSerialization。IOS5.0之后系统提供的。

提到数据交换格式首先应该考虑的是JSON,而不是Xml。因为JSON更加简单,效率更高。

增 删 改 查 都是对字典和数组来说的。因此以后都是对数组和字典的增删改查。

顶层对象必须是NSArray或者NSDictionary

所有的对象必须是NSStringNSNumberNSArrayNSDictionaryNSNull的实例

所有NSDictionarykey必须是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;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值