|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- # JSONModel - Magical Data Modeling Framework for JSON
-
- JSONModel allows rapid creation of smart data models. You can use it in your
- iOS, macOS, watchOS and tvOS apps. Automatic introspection of your model classes
- and JSON input drastically reduces the amount of code you have to write.
-
- See [CHANGELOG.md](CHANGELOG.md) for details on changes.
-
- ## Installation
-
- ### CocoaPods
-
- ```ruby
- pod 'JSONModel'
- ```
-
- ### Carthage
-
- ```ruby
- github "jsonmodel/jsonmodel"
- ```
-
- ### Manual
-
- 0. download the JSONModel repository
- 0. copy the JSONModel sub-folder into your Xcode project
- 0. link your app to SystemConfiguration.framework
-
- ## Basic Usage
-
- Consider you have JSON like this:
-
- ```json
- { "id": 10, "country": "Germany", "dialCode": 49, "isInEurope": true }
- ```
-
- - create a JSONModel subclass for your data model
- - declare properties in your header file with the name of the JSON keys:
-
- ```objc
- @interface CountryModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *country;
- @property (nonatomic) NSString *dialCode;
- @property (nonatomic) BOOL isInEurope;
- @end
- ```
-
- There's no need to do anything in the implementation (`.m`) file.
-
- - initialize your model with data:
-
- ```objc
- NSError *error;
- CountryModel *country = [[CountryModel alloc] initWithString:myJson error:&error];
- ```
-
- 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:
-
- - convert `id` from string (in the JSON) to an `int` for your class
- - copy the `country` value
- - convert `dialCode` from a number (in the JSON) to an `NSString` value
- - copy the `isInEurope` value
-
- All you have to do is define the properties and their expected types.
-
- ## Examples
-
- ### Automatic name based mapping
-
- ```json
- {
- "id": 123,
- "name": "Product name",
- "price": 12.95
- }
- ```
-
- ```objc
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *name;
- @property (nonatomic) float price;
- @end
- ```
-
- ### Model cascading (models including other models)
-
- ```json
- {
- "orderId": 104,
- "totalPrice": 13.45,
- "product": {
- "id": 123,
- "name": "Product name",
- "price": 12.95
- }
- }
- ```
-
- ```objc
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *name;
- @property (nonatomic) float price;
- @end
-
- @interface OrderModel : JSONModel
- @property (nonatomic) NSInteger orderId;
- @property (nonatomic) float totalPrice;
- @property (nonatomic) ProductModel *product;
- @end
- ```
-
- ### Model collections
-
- ```json
- {
- "orderId": 104,
- "totalPrice": 103.45,
- "products": [
- {
- "id": 123,
- "name": "Product #1",
- "price": 12.95
- },
- {
- "id": 137,
- "name": "Product #2",
- "price": 82.95
- }
- ]
- }
- ```
-
- ```objc
- @protocol ProductModel;
-
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *name;
- @property (nonatomic) float price;
- @end
-
- @interface OrderModel : JSONModel
- @property (nonatomic) NSInteger orderId;
- @property (nonatomic) float totalPrice;
- @property (nonatomic) NSArray <ProductModel> *products;
- @end
- ```
-
- Note: the angle brackets after `NSArray` contain a protocol. This is not the
- same as the Objective-C generics system. They are not mutually exclusive, but
- for JSONModel to work, the protocol must be in place.
-
- Also property can have generics info for compiler
- ```objc
- @interface OrderModel : JSONModel
- @property (nonatomic) NSInteger orderId;
- @property (nonatomic) float totalPrice;
- @property (nonatomic) NSArray<ProductModel *> <ProductModel> *products;
- @end
- ```
-
- ### Nested key mapping
-
- ```json
- {
- "orderId": 104,
- "orderDetails": {
- "name": "Product #1",
- "price": {
- "usd": 12.95
- }
- }
- }
- ```
-
- ```objc
- @interface OrderModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *productName;
- @property (nonatomic) float price;
- @end
-
- @implementation OrderModel
-
- + (JSONKeyMapper *)keyMapper
- {
- return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:@{
- @"id": @"orderId",
- @"productName": @"orderDetails.name",
- @"price": @"orderDetails.price.usd"
- }];
- }
-
- @end
- ```
-
- ### Map automatically to snake_case
-
- ```json
- {
- "order_id": 104,
- "order_product": "Product #1",
- "order_price": 12.95
- }
- ```
-
- ```objc
- @interface OrderModel : JSONModel
- @property (nonatomic) NSInteger orderId;
- @property (nonatomic) NSString *orderProduct;
- @property (nonatomic) float orderPrice;
- @end
-
- @implementation OrderModel
-
- + (JSONKeyMapper *)keyMapper
- {
- return [JSONKeyMapper mapperForSnakeCase];
- }
-
- @end
- ```
-
- ### Optional properties (i.e. can be missing or null)
-
- ```json
- {
- "id": 123,
- "name": null,
- "price": 12.95
- }
- ```
-
- ```objc
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString <Optional> *name;
- @property (nonatomic) float price;
- @property (nonatomic) NSNumber <Optional> *uuid;
- @end
- ```
-
- ### Ignored properties (i.e. JSONModel completely ignores them)
-
- ```json
- {
- "id": 123,
- "name": null
- }
- ```
-
- ```objc
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString <Ignore> *customProperty;
- @end
- ```
-
- ### Making scalar types optional
-
- ```json
- {
- "id": null
- }
- ```
-
- ```objc
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @end
-
- @implementation ProductModel
-
- + (BOOL)propertyIsOptional:(NSString *)propertyName
- {
- if ([propertyName isEqualToString:@"id"])
- return YES;
-
- return NO;
- }
-
- @end
- ```
-
- ### Export model to `NSDictionary` or JSON
-
- ```objc
- ProductModel *pm = [ProductModel new];
- pm.name = @"Some Name";
-
- // convert to dictionary
- NSDictionary *dict = [pm toDictionary];
-
- // convert to json
- NSString *string = [pm toJSONString];
- ```
-
- ### Custom data transformers
-
- ```objc
- @interface JSONValueTransformer (CustomTransformer)
- @end
-
- @implementation JSONValueTransformer (CustomTransformer)
-
- - (NSDate *)NSDateFromNSString:(NSString *)string
- {
- NSDateFormatter *formatter = [NSDateFormatter new];
- formatter.dateFormat = APIDateFormat;
- return [formatter dateFromString:string];
- }
-
- - (NSString *)JSONObjectFromNSDate:(NSDate *)date
- {
- NSDateFormatter *formatter = [NSDateFormatter new];
- formatter.dateFormat = APIDateFormat;
- return [formatter stringFromDate:date];
- }
-
- @end
- ```
-
- ### Custom getters/setters
-
- ```objc
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *name;
- @property (nonatomic) float price;
- @property (nonatomic) NSLocale *locale;
- @end
-
- @implementation ProductModel
-
- - (void)setLocaleWithNSString:(NSString *)string
- {
- self.locale = [NSLocale localeWithLocaleIdentifier:string];
- }
-
- - (void)setLocaleWithNSDictionary:(NSDictionary *)dictionary
- {
- self.locale = [NSLocale localeWithLocaleIdentifier:dictionary[@"identifier"]];
- }
-
- - (NSString *)JSONObjectForLocale
- {
- return self.locale.localeIdentifier;
- }
-
- @end
- ```
-
- ### Custom JSON validation
-
- ```objc
-
- @interface ProductModel : JSONModel
- @property (nonatomic) NSInteger id;
- @property (nonatomic) NSString *name;
- @property (nonatomic) float price;
- @property (nonatomic) NSLocale *locale;
- @property (nonatomic) NSNumber <Ignore> *minNameLength;
- @end
-
- @implementation ProductModel
-
- - (BOOL)validate:(NSError **)error
- {
- if (![super validate:error])
- return NO;
-
- if (self.name.length < self.minNameLength.integerValue)
- {
- *error = [NSError errorWithDomain:@"me.mycompany.com" code:1 userInfo:nil];
- return NO;
- }
-
- return YES;
- }
-
- @end
- ```
-
- ## License
-
- MIT licensed - see [LICENSE](LICENSE) file.
-
- ## Contributing
-
- We love pull requests! See [CONTRIBUTING.md](CONTRIBUTING.md) for full details.
|