Skip to content

luna-moonfang/JSONModel

 
 

Repository files navigation

Magical Data Modelling Framework for JSON

Version 1.0.2

#####NB: Swift works in a different way under the hood than Objective-C. Therefore I can't find a way to re-create JSONModel in Swift. JSONModel in Objective-C works in Swift apps through CocoaPods or as an imported Objective-C library.


If you like JSONModel and use it, could you please:

  • star this repo

  • send me some feedback. Thanks!


JSONModel for iOS and OSX

JSONModel is a library, which allows rapid creation of smart data models. You can use it in your iOS or OSX apps.

JSONModel automatically introspects your model classes and the structure of your JSON input and reduces drastically the amount of code you have to write.

快速创建数据模型。 自动解析模型类和json结构,无需太多代码。


Adding JSONModel to your project

Requirements

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

Get it as: 1) source files

  1. Download the JSONModel repository as a zip file or clone it
  2. Copy the JSONModel sub-folder into your Xcode project
  3. Link your app to SystemConfiguration.framework

or 2) via Cocoa pods

In your project's Podfile add the JSONModel pod:

pod 'JSONModel'

If you want to read more about CocoaPods, have a look at this short tutorial.

Source code documentation

The source code includes class docs, which you can build yourself and import into Xcode:

TODO: 安装appledoc工具

  1. If you don't already have appledoc installed, install it with homebrew by typing brew install appledoc.
  2. Install the documentation into Xcode by typing appledoc . in the root directory of the repository.
  3. Restart Xcode if it's already running.

Basic usage

Consider you have a JSON like this:

{"id":"10", "country":"Germany", "dialCode": 49, "isInEurope":true}
  • Create a new Objective-C class for your data model and make it inherit the JSONModel class.

    为数据模型创建oc类,继承JSONModel

  • Declare properties in your header file with the name of the JSON keys:

    把JSON的key在h文件声明成属性,m文件不动:

#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

There's no need to do anything in the .m file.

  • Initialize your model with data:

    用json数据初始化模型:

#import "CountryModel.h"
...

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

If the validation of the JSON passes you have all the corresponding properties in your model populated from the JSON. JSONModel will also try to convert as much data to the types you expect, in the example above it will:

如果json有model中对应的属性,JSONModel会尽可能做类型转换,以上面的为例:会

  • convert "id" from string (in the JSON) to an int for your class

    id从string转成int

  • just copy country's value

    country从string到string,只赋值

  • convert dialCode from number (in the JSON) to an NSString value

    dialCode从number到NSString

  • finally convert isInEurope to a BOOL for your BOOL property

    isInEurope转成BOOL

And the good news is all you had to do is define the properties and their expected types.

你要做的就是定义好属性和它们的类型。


Online tutorials

Official website: http://www.jsonmodel.com

Class docs online: http://jsonmodel.com/docs/

Step-by-step tutorials:


Examples

Automatic name based mapping

{
  "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

Model cascading (models including other models)

{
  "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

Model collections

{
  "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
// 注:通过命名和类名相同的协议名,让指定数组中元素的类型
// 参考文章 http://blog.zephyrleaves.net
// 和run time相关?

@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

Key mapping

比如下面的例子,真正有用的属性就三个,但后两个的层次比较深,中间隔着一些无用的嵌套,这时可以用key mapping做映射,缩短路径,也可以用来改名,第一个属性从order_id改为id

{
  "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

Global key mapping (applies to all models in your app)

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

Map automatically under_score case to camelCase

{
  "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

Optional properties (i.e. can be missing or 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

Ignored properties (i.e. JSONModel completely ignores them)

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

@implementation ProductModel @end

Make all model properties optional (avoid if possible)

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

Lazy convert collection items from dictionaries to models

延迟有什么用?

{
  "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, ConvertOnDemand>* products; @end

@implementation OrderModel @end

Using the built-in thin HTTP client

//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 ...
                                   
                               }];

Export model to NSDictionary or to JSON text

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];

Custom data transformers

@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
  • json validation
  • error handling
  • custom data validation
  • automatic compare and equality features
  • and more.

Misc

Author: Marin Todorov

Contributors: Christian Hoffmann, Mark Joslin, Julien Vignali, Symvaro GmbH, BB9z. Also everyone who did successful pull requests.

Change log : https://github.com/icanzilb/JSONModel/blob/master/Changelog.md


License

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


Contribution guidelines

NB! If you are fixing a bug you discovered, please add also a unit test so I know how exactly to reproduce the bug before merging.

About

Magical Data Modelling Framework for JSON. Create rapidly powerful, atomic and smart data model classes

Resources

Stars

0 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages

  • Objective-C 99.8%
  • Ruby 0.2%