一、什么是Json?
关于Json的解释还是看百度百科是怎么解释的《百度百科---JSON》,这里还是比较专业的。首先我们已经知道了我们对象是什么也知道一些它的基本格式(百度百科有说明)。
我们也来看看我保存在本地的一个Json文件,来具体分析一下它的格式。
先选择左上角的“Outline”模式,我们看见从左到右就是这么三列,分别是“Type”---类型,“Value”---值和“Name”---名字。有的“Name”前面还有一个三角箭头,可以点开看看到底是什么。
里面是字符串形式的数据,再里面就没有什么了。其他的一些就都是形式一样的。
我们还可以选择左上角的Text模式查看这个Json文档。
看见的没一个Value里面的内容的形式都是一样的。
这个Json文件的结构大致是这样的:
最外层是一个字典,字典的一个key CATALOG 对应的Vaule CD 是一个数组,这个数组有25个元素,每个元素又是一个字典,字典里面是六个键值对。这个就是这个Json文件的结构了。
二、Json的解析
Json的解析在Xcode中其实只有简单的三步。
第一步:把字符串形式的链接转换为url形式;
第二步:使用NSData向服务器发送请求下载数据,转化保存为NSData形式;
第三步:调用系统类NSJSONSerialization的 + (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;把返回的数据存储为数组或是字典。为什么是数组和字典呢?
在Xcode里面我们可以在NSJSONSerialization类里面找到这样一个方法:
/* Returns YES if the given object can be converted to JSON data, NO otherwise. The object must have the following properties: - Top level object is an NSArray or NSDictionary - All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull - All dictionary keys are NSStrings - NSNumbers are not NaN or infinity Other rules may apply. Calling this method or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data. */ + (BOOL)isValidJSONObject:(id)obj;
这个方法是用来判断一个对象是不是一个Json,如果是就返回YES,否则就返回NO。再来看看四行以 “—”开头的说明。
第一句:最外层不是数组就是字典
第二句:所有的对象都是NSString, NSNumber, NSArray, NSDictionary, or NSNull 类型的,(还要包括BOOL类型的)
第三句:所有字典的key都是NSString类型的
第四句:所有的NSNumbers不是NaN(还不知道他的解释)也不是无穷大
这个方法也告诉了我们为什么Json的最外层是数组或是字典和Json中值的类型。
那么解析的三步使用代码怎么实现呢?其实在代码中写简单一点也就三行代码。
NSURL * url = [NSURL URLWithString:PATH];//把字符串类型是路径转换为NSURL 类型的 NSData * data = [NSData dataWithContentsOfURL:url];/向从URL中拿数据, NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];//用一个字典接收返回来的数据。
这里方法里面的参数为什么是这样的?我们可以找到对应的方法的官方的解释。我们只需要按住键盘的“command”键,鼠标移动到方法那里,点击就能自动跳转到相应的方法的申明那里了。
/* Create a Foundation object from JSON data. Set the NSJSONReadingAllowFragments option if the parser should allow top-level objects that are not an NSArray or NSDictionary. Setting the NSJSONReadingMutableContainers option will make the parser generate mutable NSArrays and NSDictionaries. Setting the NSJSONReadingMutableLeaves option will make the parser generate mutable NSString objects. If an error occurs during the parse, then the error parameter will be set and the result will be nil. The data must be in one of the 5 supported encodings listed in the JSON specification: UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE. The data may or may not have a BOM. The most efficient encoding to use for parsing is UTF-8, so if you have a choice in encoding the data passed to this method, use UTF-8. */ + (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
剩下的工作就不难完成了。就是怎么从返回的字典中拿我们需要的数据了。这些就和Json的解析没多大关系了。只要理清层级关系,一点一点的拿就行了。
获取字典里面的数据我们可以建立一个模型来获取。在这个Json文件里面,每一张专辑都有六个成员,那么我们就可以以专辑为单位建立模型。然后再把这些模型存储进一个数组里面就可以了。
三、建立模型
上面已经说明了这个Json里面的数据的特点和结构的规律,下面的建立模型就不难了,我们直接看代码。
①建立一个模型类DataModel,它里面有六个成员:
@property (nonatomic,copy) NSString * ARTIST; //艺术家 @property (nonatomic,copy) NSString * COMPANY; //公司 @property (nonatomic,copy) NSString * COUNTRY; //国家 @property (nonatomic,copy) NSString * PRICE; //价格 @property (nonatomic,copy) NSString * TITLE; //专辑名 @property (nonatomic,copy) NSString * YEAR; //年代
我们再在解析这个Json类里面声明一个可变数组- (NSArray *)preaseJson;
接下里就是解析的代码和模型数据打包了。这段代码理解起来也不困难。
- (NSArray *)preaseJson{ /****************************JSON的解析*************************************/ NSURL * url = [NSURL URLWithString:PATH]; NSData * data = [NSData dataWithContentsOfURL:url]; NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSArray * cdArr = dic[@"CATALOG"][@"CD"]; //遍历CD对应的数组 for (NSDictionary * di in cdArr) { DataModel * mo = [[DataModel alloc] init]; // mo.ARTIST = di[@"ARTIST"]; // mo.COMPANY = di[@"COMPANY"]; // mo.COUNTRY = di[@"COUNTRY"]; // mo.PRICE = di[@"PRICE"]; // mo.TITLE = di[@"TITLE"]; // mo.YEAR = di[@"YEAR"]; // [_arr addObject:mo]; // KVC (键 --- 值编码) //这种方法和上面注释的方法二选一,使用这种方法就需要在数据模型里面实现一个打印的方法(这个打印方法可没有),且上面声明的成员的名字必须和字典里面的key名一样。 [mo setValuesForKeysWithDictionary:di]; [_arr addObject:mo]; } return _arr; }
最后就是打印了
- (void)print{ MyJson * myjson = [[MyJson alloc] init]; NSArray * array = [myjson preaseJson]; int i = 0; for (DataModel * dm in array) { printf("------------- %d -------------\n",++i); printf(" ARTIST : %s\n",[[dm ARTIST] UTF8String]); //艺术家 printf(" COMPANY : %s\n",[[dm COMPANY] UTF8String]);//唱片公司 printf(" COUNTRY : %s\n",[[dm COUNTRY] UTF8String]);//国家 printf(" PRICE : %s\n",[[dm PRICE] UTF8String]); //价格 printf(" TITLE : %s\n",[[dm TITLE] UTF8String]); //专辑名 printf(" YEAR : %s\n",[[dm YEAR] UTF8String]); //年代 // [dm show]; //这个show方法也是把上面的6行printf封装一下 } } + (void)test{ MyJson * js = [[MyJson alloc] init]; [js print]; }
最后在main函数里面就只有一条语句:[MyJson test];
就这样数据基本解析出来了。最后的打印结果:一共25个。
如果我们想把数据保存进一个txt文档,就需要文件操作了。前面已经介绍了一种文件操作的方式,现在再来介绍一种文件操作的方式。
四、NSFileManager 类
其实这里的文件的操作也不难,代码量也不大。
+ (void)dataPacket{ MyJson * json = [[MyJson alloc] init]; NSArray * dataArr = [json preaseJson]; // 数组dataArr中存储 解析后的数据模型 NSMutableString * str = [[NSMutableString alloc] init];//新建一个可变字符串 NSFileManager * myFile = [NSFileManager defaultManager]; int i = 0; for (DataModel * md in dataArr) { [str appendFormat:@"%d %@",++i,@"-----------------------------\n"]; [str appendFormat:@"%@%@%@",@" ARTIST : ",md.ARTIST,@"\n"]; [str appendFormat:@"%@%@%@",@" COMPANY : ",md.COMPANY,@"\n"]; [str appendFormat:@"%@%@%@",@" COUNTRY : ",md.COUNTRY,@"\n"]; [str appendFormat:@"%@%@%@",@" PRICE : ",md.PRICE,@"\n"]; [str appendFormat:@"%@%@%@",@" TITLE : ",md.TITLE,@"\n"]; [str appendFormat:@"%@%@%@",@" YEAR : ",md.YEAR,@"\n"]; } NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding]; [myFile createFileAtPath:SAVEPATH contents:data attributes:nil]; }
最后几句中的SAVEPATH就是存储路径,需要带上文件格式的,就像你看一个文件的属性里面显示的那样,如:/user/Desktop/123.txt。
最后我们打开看看里面保存的是Xcode打印出来的形式也是一样的。我们也需在main加上一句代码,代码我就不写了。
关于KVC 键值编码还不是很会使用,以后熟练了再写出来。
最后上传一张图片关于使用苹果自带浏览器打开json文档乱码的问题是怎么解决的。
版权声明:本文为博主原创文章,未经博主允许不得转载。