iOS开发人员已经习惯于将JSON转换为字典或者数组来进行操作了,接下来我要做的事情,可能匪夷所思,但是,对WP和Android开发人员而言,他们更倾向于将JSON转换为实体对象进行操作。
我所设计的客户端框架,三个平台之间互相取长补短,保持统一的思想,而其中最重要的一环就是,面向对象的编程方式。
书接上文,我在异步调用完MobileAPI并成功获取到JSON后,仅仅将其转换为jsonValue,如下所示:
后续要做的事情,就是把jsonValue转换为实体对象了。
首先,要说一下JSON的格式。
MobileAPI返回的JSON字符串有几种格式:
1)单一实体:
a)简单属性:
- {
- "userName": "baobao",
- "userAge": 18
- }
b)属性中有复合属性,且该复合属性是另一个自定义实体:
- {
- "UserId": 1,
- "UserInfo": {
- "userName": "baobao",
- "userAge": 18
- }
- }
c)属性中有复合属性,且该复合属性是一个数组:
- {
- "Career": "IT",
- "Users": [
- {
- "userName": "Bill.Gates",
- "userAge": 60
- },
- {
- "userName": "baobao",
- "userAge": 18
- }
- ]
- }
2)数组
a)规范的写法:
- {
- "Users": [
- {
- "userName": "Bill.Gates",
- "userAge": 60
- }
- {
- "userName": "baobao",
- "userAge": 18
- }
- ]
- }
b)不规范的写法:
- [
- {
- "userName": "Bill.Gates",
- "userAge": 60
- },
- {
- "userName": "baobao",
- "userAge": 18
- }
- ]
对以上格式进行归纳,我们发现,只需要指定好:
1)整个JSON字符串是规范的(这时是一个字典),还是不规范的(这时是一个数组)
2)对于规范的JSON字符串,每个JSON字段映射为实体的哪个字段,就是说,from是什么,to是什么?
3)实体字段的数据类型。对于JSON而言,简单类型,只有NSString和NSNumber两种(日期按字符串对待,布尔值按整数0和1对待)。复合类型,有2种:要么是一个自定义实体(这时是一个字典),要么是一个数组。
基于此,我们创建统一格式的实体格式如下:
//以下为UserEntity.h文件:
- #import <Foundation/Foundation.h>
- @class ObjectMapping;
- @interface UserEntity : NSObject
- {
- NSString *name;
- NSNumber *age;
- }
- @property (nonatomic,retain) NSString *name;
- @property (nonatomic,retain) NSNumber *age;
- - (ObjectMapping *)objectMapping;
- @end
- //以下为UserEntity.m文件:
- #import "UserEntity.h"
- #import "ObjectMapping.h"
- @implementation UserEntity
- @synthesize name;
- @synthesize age;
- - (ObjectMapping *)objectMapping {
- ObjectMapping *mapping = [ObjectMapping mappingForClass:[UserEntity class]];
- [mapping converEntityFromJsonToEntity:@"userName" to:@"name" withClass: @"NSString"];
- [mapping converEntityFromJsonToEntity:@"userAge" to:@"age" withClass: @"NSNumber"];
- return mapping;
- }
- - (void)dealloc {
- [name release];
- [age release];
- [super dealloc];
- }
- @end
在格式统一的情况下,我们来讨论在MyApp中是如何使用的,参见APageViewController.m文件,我们继续改造上一节没有完成的requestFinished方法:
通过ObjectMappingLoader的loadObjectWithClassName方法,我们将jsonValue转换为实体 result,然后再一次将result强制转换为WeatherWrapEntity类型的实体。接下来我们就可以使用 weatherWrapEntity实体中的任何属性了,都是JSON里面返回的数据。
使用起来非常简单,但这一切都是MyLib类库下ObjectMapping目录中的3个类来实现的:
原理比较简单,使用到了迭代算法,把JSON格式的字符串先转换为字典,然后再迭代之,转换为实体。
本节源码如下: YoungHeart-Chapter-05-1.zip
另外,对各种情况的模拟,参见MyApp下的MyAppTest目录,这是一个单元测试,相应的Target为MyAppTests,每次修改 MyLib的时候不是要把libMyLib.a重新引入到MyApp项目的MyApp这个Target中嘛,请同时将其也引入到MyAppTests这个 Target中。