iOS中JSONModel的使用

流弊的JSON数据模型框架

https://github.com/jsonmodel/jsonmodel

版本 1.3.0


如果你喜欢JSONModel,并且使用了它,请你:

  • star一下

  • 给我一些反馈. 多谢!


JSONModel for iOS and OSX

JSONModel 是一个能够快速巧妙的创建数据模型的库. 你可以在 iOS or OSX APP中使用它.

JSONModel 自动检查JOSN模型和结构体, 彻底的减少你的代码量.


添加JSONModel到你的项目中

要求

  • 支持持ARC; iOS 5.0+ / OSX 10.7+
  • SystemConfiguration.framework

as: 1) 源文件

1.下载JSONModel.zip文件
2.将它拷贝到你的项目中
3.导入SystemConfiguration.framework框架

or 2)使用 CocoaPods

pod 'JSONModel'

如果你想关于CocoaPods了解更多,请参考这个简单的教程.

or 3) 使用 Carthage

在你的项目的Cartfile添加JSONModel:

github "jsonmodel/jsonmodel"

文档

你可以查看在线阅读文档: http://cocoadocs.org/docsets/JSONModel


基本使用

涉想你的JSON数据像这样:

{ "id": "10", "country": "Germany", "dialCode": 49, "isInEurope": true }
  • 为你的数据模型创建一个Objective-C的类,继承自JSONModel.
  • 将JSON中的keys在.h文件中声明为属性:
#import "JSONModel.h"

@interface CountryModel : JSONModel

@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* country;
@property (strong, nonatomic) NSString* dialCode;
@property (assign, nonatomic) BOOL isInEurope;

@end

在.m文件中不需要做任何事情.

  • 用数据初始化你的model:
#import "CountryModel.h"
...

NSString* json = (fetch here JSON from Internet) ...
NSError* err = nil;
CountryModel* country = [[CountryModel alloc] initWithString:json error:&err];

如果传过来的JSON合法,你所定义的所有的属性都会与该JSON的值想对应,甚至JSONModel会尝试去转换数据为你期望的类型,如上所示:

  • 转换id,从字符串转换为int
  • 只需要拷贝一下country的值
  • 转换diaCode,从number转换为字符串
  • 最后一个是将isInEurope转换为BOOL属性

所以,你所需要做的就是将你的属性定义为期望的类型.


在线教程

官方网站: http://www.jsonmodel.com

在线文档: http://jsonmodel.com/docs/

傻瓜教程:


举个栗子

命名自动匹配

{
  "id": "123",
  "name": "Product name",
  "price": 12.95
}
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@end

@implementation ProductModel
@end

模型嵌套 (模型包含其他模型)

{
  "order_id": 104,
  "total_price": 13.45,
  "product" : {
    "id": "123",
    "name": "Product name",
    "price": 12.95
  }
}

@interface OrderModel : JSONModel
@property (assign, nonatomic) int order_id;
@property (assign, nonatomic) float total_price;
@property (strong, nonatomic) ProductModel* product;
@end

@implementation OrderModel
@end

模型集合

{
  "order_id": 104,
  "total_price": 103.45,
  "products" : [
    {
      "id": "123",
      "name": "Product #1",
      "price": 12.95
    },
    {
      "id": "137",
      "name": "Product #2",
      "price": 82.95
    }
  ]
}
@protocol ProductModel
@end
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@end

@implementation ProductModel
@end

@interface OrderModel : JSONModel
@property (assign, nonatomic) int order_id;
@property (assign, nonatomic) float total_price;
@property (strong, nonatomic) NSArray<ProductModel>* products;
@end

@implementation OrderModel
@end

注意: 尖括号后 <code>NSArray</code> 包含一个协议. 这跟Objective-C原生的泛型不是一个概念. 他们不会冲突, 但对于JSONModel来说,协议必须在一个地方声明.

key映射

{
  "order_id": 104,
  "order_details" : [
    {
      "name": "Product#1",
      "price": {
        "usd": 12.95
      }
    }
  ]
}

@interface OrderModel : JSONModel
@property (assign, nonatomic) int id;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSString* productName;
@end

@implementation OrderModel

+(JSONKeyMapper*)keyMapper
{
  return [[JSONKeyMapper alloc] initWithDictionary:@{
    @"order_id": @"id",
    @"order_details.name": @"productName",
    @"order_details.price.usd": @"price"
  }];
}

@end

设置全局键映射(应用于所有model)

[JSONModel setGlobalKeyMapper:[
    [JSONKeyMapper alloc] initWithDictionary:@{
      @"item_id":@"ID",
      @"item.name": @"itemName"
   }]
];

设置下划线自动转驼峰

{
  "order_id": 104,
  "order_product" : @"Product#1",
  "order_price" : 12.95
}
@interface OrderModel : JSONModel

@property (assign, nonatomic) int orderId;
@property (assign, nonatomic) float orderPrice;
@property (strong, nonatomic) NSString* orderProduct;

@end

@implementation OrderModel

+(JSONKeyMapper*)keyMapper
{
  return [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];
}

@end

可选属性 (就是说这个属性可以为null或者为空)

{
  "id": "123",
  "name": null,
  "price": 12.95
}
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString<Optional>* name;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSNumber<Optional>* uuid;
@end

@implementation ProductModel
@end

忽略属性 (就是完全忽略这个属性)

{
  "id": "123",
  "name": null
}
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString<Ignore>* customProperty;
@end

@implementation ProductModel
@end

设置所有的属性为可选(所有属性值可以为空)

@implementation ProductModel
+(BOOL)propertyIsOptional:(NSString*)propertyName
{
  return YES;
}
@end

使用JSONModel自带的 HTTP 请求


//add extra headers
[[JSONHTTPClient requestHeaders] setValue:@"MySecret" forKey:@"AuthorizationToken"];

//make post, get requests
[JSONHTTPClient postJSONFromURLWithString:@"http://mydomain.com/api"
                                   params:@{@"postParam1":@"value1"}
                               completion:^(id json, JSONModelError *err) {

                                   //check err, process json ...

                               }];

将model转化为字典或者json格式的字符串


ProductModel* pm = [[ProductModel alloc] initWithString:jsonString error:nil];
pm.name = @"Changed Name";

//convert to dictionary
NSDictionary* dict = [pm toDictionary];

//convert to text
NSString* string = [pm toJSONString];

自定义数据的转换


@implementation JSONValueTransformer (CustomTransformer)

- (NSDate *)NSDateFromNSString:(NSString*)string {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:APIDateFormat];
    return [formatter dateFromString:string];
}

- (NSString *)JSONObjectFromNSDate:(NSDate *)date {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:APIDateFormat];
    return [formatter stringFromDate:date];
}

@end

自定义处理指定的属性


@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSLocale *locale;
@end

@implementation ProductModel

// Convert and assign the locale property
- (void)setLocaleWithNSString:(NSString*)string {
    self.locale = [NSLocale localeWithLocaleIdentifier:string];
}

- (NSString *)JSONObjectForLocale {
    return self.locale.localeIdentifier;
}

@end

自定义JSON校验


@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSLocale *locale;
@property (strong, nonatomic) NSNumber <Ignore> *minNameLength;
@end

@implementation ProductModel

- (BOOL)validate:(NSError *__autoreleasing *)error {
    BOOL valid = [super validate:error];

    if (self.name.length < self.minNameLength.integerValue) {
        *error = [NSError errorWithDomain:@"me.mycompany.com" code:1 userInfo:nil];
        valid = NO;
    }

    return valid;
}

@end

  • 错误处理
  • 自定义数据校验
  • 自动比较和相等判断
  • 更多.

Misc

作者: Marin Todorov

参与者: Christian Hoffmann, Mark Joslin, Julien Vignali, Symvaro GmbH, BB9z.
任何人都可以 pull requests.

更新log : https://github.com/jsonmodel/jsonmodel/blob/master/CHANGELOG.md

Utility to generate JSONModel classes from JSON data: https://github.com/dofork/json2object


许可

This code is distributed under the terms and conditions of the MIT license.


参考指南

NB! 如果你解决了你发现的某个BUG, 请添加单元测试,这样以便我在合并之前复现这个BUG.


使用问题汇总

1、1.4.0版本的JSONKeyMapper

如果需要替换服务端返回来的key,需要按照下面的结构@{@"你的key":@"接口返回的key"},并且请使用initWithModelToJSONDictionary这个方法。

+ (JSONKeyMapper *)keyMapper {
    return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:
            @{
              @"isChecked":@"ischecked",
              @"tagId":@"tagid",
              @"tagName":@"tagname",
              @"tagValue":@"tagvalue"
              }];
}
2、模型包含模型时的使用, 被包含的模型需要声明protocol

eg:KSAlreadyBuyListModel 包含一个属性KSAlreadyBuyModel, 我们需要将KSAlreadyBuyModel声明protocol,不然会解析失败。

@class StoryModel, AblumModel;

@protocol KSAlreadyBuyModel <NSObject>
@end

@interface KSAlreadyBuyModel : KSBaseModel

@property (nonatomic, strong) StoryModel *storyModel;
@property (nonatomic, strong) AblumModel *ablumModel;

@end

@protocol KSAlreadyBuyListModel <NSObject>
@end

@interface KSAlreadyBuyListModel : KSBaseModel

@property (nonatomic, copy) NSString *contentid;
@property (nonatomic, copy) NSString *contenttype;
@property (nonatomic, copy) NSString *iconurl;
@property (nonatomic, copy) NSString *orderno;
@property (nonatomic, copy) NSString *productid;
@property (nonatomic, copy) NSString *productname;
@property (nonatomic, copy) NSString *realityprice;
@property (nonatomic, strong) KSAlreadyBuyModel *param;

@end
3、如果你在同一个.h中为了解析所有数据,创建了多个model,一定要记得这些model在.m文件中实现他们。eg:上面的第二个。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容