YYModel

High performance model framework for iOS/OSX.

Subscribe to updates I use YYModel


Statistics on YYModel

Number of watchers on Github 3382
Number of open issues 104
Average time to close an issue 8 days
Main language Objective-C
Average time to merge a PR 1 day
Open pull requests 20+
Closed pull requests 14+
Last commit 10 months ago
Repo Created over 2 years ago
Repo Last Updated 2 months ago
Size 920 KB
Organization / Authoribireme
Latest Release1.0.4
Contributors6
Page Updated
Do you use YYModel? Leave a review!
View open issues (104)
View YYModel activity
View on github
Latest Open Source Launches
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating YYModel for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

YYModel

License MIT  Carthage compatible  CocoaPods  CocoaPods  Build Status  codecov.io

High performance model framework for iOS/OSX.
(It's a component of YYKit)

Performance

Time cost (process GithubUser 10000 times on iPhone 6):

Benchmark result

See Benchmark/ModelBenchmark.xcodeproj for more benchmark case.

Features

  • High performance: The conversion performance is close to handwriting code.
  • Automatic type conversion: The object types can be automatically converted.
  • Type Safe: All data types will be verified to ensure type-safe during the conversion process.
  • Non-intrusive: There is no need to make the model class inherit from other base class.
  • Lightwight: This library contains only 5 files.
  • Docs and unit testing: 100% docs coverage, 99.6% code coverage.

Usage

Simple model json convert

// JSON:
{
    "uid":123456,
    "name":"Harry",
    "created":"1965-07-31T00:00:00+0000"
}

// Model:
@interface User : NSObject
@property UInt64 uid;
@property NSString *name;
@property NSDate *created;
@end
@implementation User
@end


// Convert json to model:
User *user = [User yy_modelWithJSON:json];

// Convert model to json:
NSDictionary *json = [user yy_modelToJSONObject];

If the type of an object in JSON/Dictionary cannot be matched to the property of the model, the following automatic conversion is performed. If the automatic conversion failed, the value will be ignored.

JSON/Dictionary Model
NSString NSNumber,NSURL,SEL,Class
NSNumber NSString
NSString/NSNumber C number (BOOL,int,float,NSUInteger,UInt64,...)
NaN and Inf will be ignored
NSString NSDate parsed with these formats:
yyyy-MM-dd
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssZ
EEE MMM dd HH:mm:ss Z yyyy
NSDate NSString formatted with ISO8601:
"YYYY-MM-dd'T'HH:mm:ssZ"
NSValue struct (CGRect,CGSize,...)
NSNull nil,0
"no","false",... @(NO),0
"yes","true",... @(YES),1

Match model property to different JSON key

// JSON:
{
    "n":"Harry Pottery",
    "p": 256,
    "ext" : {
        "desc" : "A book written by J.K.Rowing."
    },
    "ID" : 100010
}

// Model:
@interface Book : NSObject
@property NSString *name;
@property NSInteger page;
@property NSString *desc;
@property NSString *bookID;
@end
@implementation Book
+ (NSDictionary *)modelCustomPropertyMapper {
    return @{@"name" : @"n",
             @"page" : @"p",
             @"desc" : @"ext.desc",
             @"bookID" : @[@"id",@"ID",@"book_id"]};
}
@end

You can map a json key (key path) or an array of json key (key path) to one or multiple property name. If there's no mapper for a property, it will use the property's name as default.

Nested model

// JSON
{
    "author":{
        "name":"J.K.Rowling",
        "birthday":"1965-07-31T00:00:00+0000"
    },
    "name":"Harry Potter",
    "pages":256
}

// Model: (no need to do anything)
@interface Author : NSObject
@property NSString *name;
@property NSDate *birthday;
@end
@implementation Author
@end

@interface Book : NSObject
@property NSString *name;
@property NSUInteger pages;
@property Author *author;
@end
@implementation Book
@end

Container property

@class Shadow, Border, Attachment;

@interface Attributes
@property NSString *name;
@property NSArray *shadows; //Array<Shadow>
@property NSSet *borders; //Set<Border>
@property NSMutableDictionary *attachments; //Dict<NSString,Attachment>
@end

@implementation Attributes
+ (NSDictionary *)modelContainerPropertyGenericClass {
    // value should be Class or Class name.
    return @{@"shadows" : [Shadow class],
             @"borders" : Border.class,
             @"attachments" : @"Attachment" };
}
@end

Whitelist and blacklist

@interface User
@property NSString *name;
@property NSUInteger age;
@end

@implementation Attributes
+ (NSArray *)modelPropertyBlacklist {
    return @[@"test1", @"test2"];
}
+ (NSArray *)modelPropertyWhitelist {
    return @[@"name"];
}
@end

Data validate and custom transform

// JSON:
{
    "name":"Harry",
    "timestamp" : 1445534567
}

// Model:
@interface User
@property NSString *name;
@property NSDate *createdAt;
@end

@implementation User
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
    NSNumber *timestamp = dic[@"timestamp"];
    if (![timestamp isKindOfClass:[NSNumber class]]) return NO;
    _createdAt = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue];
    return YES;
}
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
    if (!_createdAt) return NO;
    dic[@"timestamp"] = @(n.timeIntervalSince1970);
    return YES;
}
@end

Coding/Copying/hash/equal/description

@interface YYShadow :NSObject <NSCoding, NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) CGSize size;
@end

@implementation YYShadow
- (void)encodeWithCoder:(NSCoder *)aCoder { [self yy_modelEncodeWithCoder:aCoder]; }
- (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; return [self yy_modelInitWithCoder:aDecoder]; }
- (id)copyWithZone:(NSZone *)zone { return [self yy_modelCopy]; }
- (NSUInteger)hash { return [self yy_modelHash]; }
- (BOOL)isEqual:(id)object { return [self yy_modelIsEqual:object]; }
- (NSString *)description { return [self yy_modelDescription]; }
@end

Installation

CocoaPods

  1. Add pod 'YYModel' to your Podfile.
  2. Run pod install or pod update.
  3. Import <YYModel/YYModel.h>.

Carthage

  1. Add github "ibireme/YYModel" to your Cartfile.
  2. Run carthage update --platform ios and add the framework to your project.
  3. Import <YYModel/YYModel.h>.

Manually

  1. Download all the files in the YYModel subdirectory.
  2. Add the source files to your Xcode project.
  3. Import YYModel.h.

Documentation

Full API documentation is available on CocoaDocs.
You can also install documentation locally using appledoc.

Requirements

This library requires iOS 6.0+ and Xcode 8.0+.

License

YYModel is provided under the MIT license. See LICENSE file for details.



============== iOS/OSX
( YYKit )

============== GithubUser 10000 (iPhone 6):

Benchmark result

Benchmark/ModelBenchmark.xcodeproj

==============

  • ****:
  • ****:
  • ****:
  • ****:
  • ****: 5 (.h)
  • ****: 100%, 99.6%

==============

Model JSON

// JSON:
{
    "uid":123456,
    "name":"Harry",
    "created":"1965-07-31T00:00:00+0000"
}

// Model:
@interface User : NSObject
@property UInt64 uid;
@property NSString *name;
@property NSDate *created;
@end
@implementation User
@end


//  JSON (NSData,NSString,NSDictionary)  Model:
User *user = [User yy_modelWithJSON:json];

//  Model  JSON :
NSDictionary *json = [user yy_modelToJSONObject];

JSON/Dictionary Model YYModel

JSON/Dictionary Model
NSString NSNumber,NSURL,SEL,Class
NSNumber NSString
NSString/NSNumber (BOOL,int,float,NSUInteger,UInt64,...)
NaN Inf
NSString NSDate :
yyyy-MM-dd
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssZ
EEE MMM dd HH:mm:ss Z yyyy
NSDate NSString ISO8601:
"YYYY-MM-dd'T'HH:mm:ssZ"
NSValue struct (CGRect,CGSize,...)
NSNull nil,0
"no","false",... @(NO),0
"yes","true",... @(YES),1

Model JSON Key

// JSON:
{
    "n":"Harry Pottery",
    "p": 256,
    "ext" : {
        "desc" : "A book written by J.K.Rowing."
    },
    "ID" : 100010
}

// Model:
@interface Book : NSObject
@property NSString *name;
@property NSInteger page;
@property NSString *desc;
@property NSString *bookID;
@end
@implementation Book
// Dict Model  JSON  Key
+ (NSDictionary *)modelCustomPropertyMapper {
    return @{@"name" : @"n",
             @"page" : @"p",
             @"desc" : @"ext.desc",
             @"bookID" : @[@"id",@"ID",@"book_id"]};
}
@end

json key (key path)

json->model json key

model->json json key (key path) json key (key path) json key

Model Model

// JSON
{
    "author":{
        "name":"J.K.Rowling",
        "birthday":"1965-07-31T00:00:00+0000"
    },
    "name":"Harry Potter",
    "pages":256
}

// Model: 
@interface Author : NSObject
@property NSString *name;
@property NSDate *birthday;
@end
@implementation Author
@end

@interface Book : NSObject
@property NSString *name;
@property NSUInteger pages;
@property Author *author; //Book  Author 
@end
@implementation Book
@end
@class Shadow, Border, Attachment;

@interface Attributes
@property NSString *name;
@property NSArray *shadows; //Array<Shadow>
@property NSSet *borders; //Set<Border>
@property NSMutableDictionary *attachments; //Dict<NSString,Attachment>
@end

@implementation Attributes
//  ( Class  Class Name )
+ (NSDictionary *)modelContainerPropertyGenericClass {
    return @{@"shadows" : [Shadow class],
             @"borders" : Border.class,
             @"attachments" : @"Attachment" };
}
@end
@interface User
@property NSString *name;
@property NSUInteger age;
@end

@implementation Attributes
// 
+ (NSArray *)modelPropertyBlacklist {
    return @[@"test1", @"test2"];
}
// 
+ (NSArray *)modelPropertyWhitelist {
    return @[@"name"];
}
@end
// JSON:
{
    "name":"Harry",
    "timestamp" : 1445534567
}

// Model:
@interface User
@property NSString *name;
@property NSDate *createdAt;
@end

@implementation User
//  JSON  Model 
//  NO Model 
// 
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
    NSNumber *timestamp = dic[@"timestamp"];
    if (![timestamp isKindOfClass:[NSNumber class]]) return NO;
    _createdAt = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue];
    return YES;
}

//  Model  JSON 
//  NO Model 
// 
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
    if (!_createdAt) return NO;
    dic[@"timestamp"] = @(n.timeIntervalSince1970);
    return YES;
}
@end

Coding/Copying/hash/equal/description

@interface YYShadow :NSObject <NSCoding, NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) CGSize size;
@end

@implementation YYShadow
// 
- (void)encodeWithCoder:(NSCoder *)aCoder { [self yy_modelEncodeWithCoder:aCoder]; }
- (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; return [self yy_modelInitWithCoder:aDecoder]; }
- (id)copyWithZone:(NSZone *)zone { return [self yy_modelCopy]; }
- (NSUInteger)hash { return [self yy_modelHash]; }
- (BOOL)isEqual:(id)object { return [self yy_modelIsEqual:object]; }
- (NSString *)description { return [self yy_modelDescription]; }
@end

==============

CocoaPods

  1. Podfile pod 'YYModel'
  2. pod install pod update
  3. <YYModel/YYModel.h>

Carthage

  1. Cartfile github "ibireme/YYModel"
  2. carthage update --platform ios framework
  3. <YYModel/YYModel.h>
  1. YYModel
  2. YYModel ()
  3. YYModel.h

============== CocoaDocs API appledoc

============== iOS 6.0 Xcode 8.0

============== YYModel MIT LICENSE

==============

iOS JSON

YYModel open issues Ask a question     (View All Issues)
  • over 1 year 黑名单和白名单
  • over 1 year 使用Archiver crash
  • over 1 year 好像不支持realm
  • over 1 year README example code error
  • over 1 year model初始化结束
  • over 1 year modelCustomPropertyMapper方法可以实现从key到keypath的映射关系吗?
  • over 1 year 修改model属性值后 yy_modelHash 发生了改变。导致model无法在NSSet中使用
  • over 1 year 使用yy_modelCopy问题
  • over 1 year swift项目中String无法自动转化为Int或者Bool
  • over 1 year ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value);
  • over 1 year ModelToJSONObjectRecursive函数中,NSData的处理问题
  • over 1 year NSDecimalNumber issue
  • over 1 year 解析数组问题
  • over 1 year 对于容器类需在modelContainerPropertyGenericClass 里面设定容器类型
  • over 1 year 请问一下在Swift里怎么使用YYModel?
  • over 1 year 支持CoreData吗
  • over 1 year Passing mapping errors
  • over 1 year 关于YYEncodingType
  • over 1 year JSON value mapping
  • almost 2 years 是否可以使用多线程遍历字典或数组进一步提高速度?
  • almost 2 years modelCustomPropertyMapper 没调用
  • almost 2 years NSDate转换问题
  • almost 2 years 关于 unsafe_unretained
  • almost 2 years a question about YYEncodingType YYEncodingGetType(const char *typeEncoding) in YYClassInfo
  • almost 2 years 处理这种类型的Model类怎么写?info是id类型的,可能是数组,也可能是字典.
  • almost 2 years 如果转化字符串类型到枚举类型
  • almost 2 years About model yy_modelIsEqual model
  • almost 2 years Some issue I have trouble in using YYModel.
  • almost 2 years 一个model中有一个字典,但是字典里边的model要根据字典里边的一个属性来判断,这种要怎么处理呢?
  • almost 2 years double类型的赋值问题
YYModel open pull requests (View All Pulls)
  • Add some small features.
  • 由自己喜好来搞的,可能需要作者再整理下
  • add modelCustomPropertyForPropertyName method
  • add modelCustomWillTransformToDictionary for custom to json.
  • 你好耀源大神。。 最近在拜读YYModel源码,想问个关于YYModel的优化问题
  • 字段数组转模型数组方法的暴露
  • bugfix: Error with parse Date from String.
  • Lanjing/code reading
  • avoid documentation issue warnings
  • modelContainerPropertyGenericClass 方法返回的 _genericCls 应该优先于属性本身的类型
  • add some useful method to YYModel
  • [bugfix] yy_modelIsEqual
  • fix readme format
  • Fix NSValue bug; update example code
  • 支持多维数组转化
  • 增加字典数组转模型数组的方法
  • fix Xcode 9 warnings
  • removed hash equality from yy_modelIsEqual:
  • fix Xcode warnings.
  • Fix type cast
YYModel list of languages used
YYModel latest release notes
1.0.4 Support pseudo generic class with protocol name, bug fixes
  • Support pseudo generic class with protocol name (similar to JSONModel)
  • Support especial keypath (such as .ext a...b) in some situation: #112
  • Fix typo
1.0.3 Support more date format
  • Added millisecond support to date parsing
1.0.2 Add more custom transform method, bug fixes
  • Add custom transform method before the default json to model
  • Fix wrong model description for NSDictionary #62
  • Fix wrong result when the property's type is id #60
Other projects in Objective-C