Commit fa4413dc authored by Sandy's avatar Sandy

Merge branch 'master' of https://git.oschina.net/gomore/total

Conflicts:
	total/GTOApp/Business/Repair/Views/GTOLicenceBoltView.m
	total/Info.plist
	total/Macro/GTOAppMacro.h
parents 9ee92af1 9bd516fb
......@@ -32,7 +32,7 @@ PODS:
- FMDB/standard (2.6.2)
- IQKeyboardManager (3.2.4)
- JPushSDK (1.8.2)
- JSONModel (1.2.0)
- JSONModel (1.7.0)
- Masonry (1.0.1)
- MBProgressHUD (0.9.2)
- MJRefresh (3.1.3)
......@@ -57,7 +57,7 @@ DEPENDENCIES:
- FMDB (~> 2.5)
- IQKeyboardManager (~> 3.2.3)
- JPushSDK (~> 1.8.2)
- JSONModel (~> 1.2.0)
- JSONModel (~> 1.7.0)
- Masonry (~> 1.0.1)
- MBProgressHUD (~> 0.9.1)
- MJRefresh (~> 3.1.0)
......@@ -76,7 +76,7 @@ SPEC CHECKSUMS:
FMDB: 854a0341b4726e53276f2a8996f06f1b80f9259a
IQKeyboardManager: 555b1231fefafb21b19278d7cca72986a27b748b
JPushSDK: c68dd04c595a5c93aa003f212974010790410d8e
JSONModel: 12523685c4b623553ccf844bbbf7007624317b2c
JSONModel: 840bc0fcffb24b8454d2c026bf26fea454b8e98d
Masonry: a1a931a0d08870ed8ae415a2ea5ea68ebcac77df
MBProgressHUD: 1569cf7ace17a8bac47aabfbb8580a49690386d1
MJRefresh: e9005c294dd8a3d08cc7c50eea2b5016673f29c4
......
../../../JSONModel/JSONModel/JSONModel/JSONModelArray.h
\ No newline at end of file
../../../JSONModel/JSONModel/JSONModelCategories/NSArray+JSONModel.h
\ No newline at end of file
../../../JSONModel/JSONModel/JSONModel/JSONModelArray.h
\ No newline at end of file
../../../JSONModel/JSONModel/JSONModelCategories/NSArray+JSONModel.h
\ No newline at end of file
//
// JSONModel.h
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// JSONModel
//
#import <Foundation/Foundation.h>
#import "JSONModelError.h"
......@@ -29,12 +18,20 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#endif
/////////////////////////////////////////////////////////////////////////////////////////////
DEPRECATED_ATTRIBUTE
@protocol ConvertOnDemand
@end
DEPRECATED_ATTRIBUTE
@protocol Index
@end
#pragma mark - Property Protocols
/**
* Protocol for defining properties in a JSON Model class that should not be considered at all
* neither while importing nor when exporting JSON.
*
* @property (strong, nonatomic) NSString&lt;Ignore&gt;* propertyName;
* @property (strong, nonatomic) NSString&lt;Ignore&gt; *propertyName;
*
*/
@protocol Ignore
......@@ -44,40 +41,16 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* Protocol for defining optional properties in a JSON Model class. Use like below to define
* model properties that are not required to have values in the JSON input:
*
* @property (strong, nonatomic) NSString&lt;Optional&gt;* propertyName;
* @property (strong, nonatomic) NSString&lt;Optional&gt; *propertyName;
*
*/
@protocol Optional
@end
/**
* Protocol for defining index properties in a JSON Model class. Use like below to define
* model properties that are considered the Model's identifier (id).
*
* @property (strong, nonatomic) NSString&lt;Index&gt;* propertyName;
*
* Make all objects compatible to avoid compiler warnings
*/
@protocol Index
@end
/**
* Make all objects Optional compatible to avoid compiler warnings
*/
@interface NSObject(JSONModelPropertyCompatibility)<Optional, Index, Ignore>
@end
/**
* ConvertOnDemand enables lazy model initialization for NSArrays of models
*
* @property (strong, nonatomic) NSArray&lt;JSONModel, ConvertOnDemand&gt;* propertyName;
*/
@protocol ConvertOnDemand
@end
/**
* Make all arrays ConvertOnDemand compatible to avoid compiler warnings
*/
@interface NSArray(JSONModelPropertyCompatibility)<ConvertOnDemand>
@interface NSObject (JSONModelPropertyCompatibility) <Optional, Ignore>
@end
/////////////////////////////////////////////////////////////////////////////////////////////
......@@ -89,28 +62,28 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
@protocol AbstractJSONModelProtocol <NSCopying, NSCoding>
@required
/**
/**
* All JSONModel classes should implement initWithDictionary:
*
* For most classes the default initWithDictionary: inherited from JSONModel itself
* should suffice, but developers have the option ot also overwrite it if needed.
* should suffice, but developers have the option to also overwrite it if needed.
*
* @param dict a dictionary holding JSON objects, to be imported in the model.
* @param err an error or NULL
*/
-(instancetype)initWithDictionary:(NSDictionary*)dict error:(NSError**)err;
- (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err;
/**
* All JSONModel classes should implement initWithData:error:
*
* For most classes the default initWithData: inherited from JSONModel itself
* should suffice, but developers have the option ot also overwrite it if needed.
* should suffice, but developers have the option to also overwrite it if needed.
*
* @param data representing a JSON response (usually fetched from web), to be imported in the model.
* @param error an error or NULL
*/
-(instancetype)initWithData:(NSData*)data error:(NSError**)error;
- (instancetype)initWithData:(NSData *)data error:(NSError **)error;
/**
* All JSONModel classes should be able to export themselves as a dictionary of
......@@ -123,9 +96,9 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @exception JSONModelTypeNotAllowedException thrown when one of your model's custom class properties
* does not have matching transformer method in an JSONValueTransformer.
*/
-(NSDictionary*)toDictionary;
- (NSDictionary *)toDictionary;
/**
/**
* Export a model class to a dictionary, including only given properties
*
* @param propertyNames the properties to export; if nil, all properties exported
......@@ -133,7 +106,7 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @exception JSONModelTypeNotAllowedException thrown when one of your model's custom class properties
* does not have matching transformer method in an JSONValueTransformer.
*/
-(NSDictionary*)toDictionaryWithKeys:(NSArray*)propertyNames;
- (NSDictionary *)toDictionaryWithKeys:(NSArray *)propertyNames;
@end
/////////////////////////////////////////////////////////////////////////////////////////////
......@@ -146,9 +119,17 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
*/
@interface JSONModel : NSObject <AbstractJSONModelProtocol, NSSecureCoding>
// deprecated
+ (NSMutableArray *)arrayOfModelsFromDictionaries:(NSArray *)array DEPRECATED_MSG_ATTRIBUTE("use arrayOfModelsFromDictionaries:error:");
+ (void)setGlobalKeyMapper:(JSONKeyMapper *)globalKeyMapper DEPRECATED_MSG_ATTRIBUTE("override +keyMapper in a base model class instead");
+ (NSString *)protocolForArrayProperty:(NSString *)propertyName DEPRECATED_MSG_ATTRIBUTE("use classForCollectionProperty:");
- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping DEPRECATED_MSG_ATTRIBUTE("use mergeFromDictionary:useKeyMapping:error:");
- (NSString *)indexPropertyName DEPRECATED_ATTRIBUTE;
- (NSComparisonResult)compare:(id)object DEPRECATED_ATTRIBUTE;
/** @name Creating and initializing models */
/**
/**
* Create a new model instance and initialize it with the JSON from a text parameter. The method assumes UTF8 encoded input text.
* @param string JSON text data
* @param err an initialization error or nil
......@@ -156,9 +137,9 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* or a property type in your model is not supported by JSONValueTransformer and its categories
* @see initWithString:usingEncoding:error: for use of custom text encodings
*/
-(instancetype)initWithString:(NSString*)string error:(JSONModelError**)err;
- (instancetype)initWithString:(NSString *)string error:(JSONModelError **)err;
/**
/**
* Create a new model instance and initialize it with the JSON from a text parameter using the given encoding.
* @param string JSON text data
* @param encoding the text encoding to use when parsing the string (see NSStringEncoding)
......@@ -166,56 +147,39 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON,
* or a property type in your model is not supported by JSONValueTransformer and its categories
*/
-(instancetype)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError**)err;
-(instancetype)initWithDictionary:(NSDictionary*)dict error:(NSError **)err;
-(instancetype)initWithData:(NSData *)data error:(NSError **)error;
- (instancetype)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError **)err;
/** @name Exporting model contents */
/**
* Export the whole object to a dictionary
* @return dictionary containing the data model
*/
-(NSDictionary*)toDictionary;
/**
/**
* Export the whole object to a JSON data text string
* @return JSON text describing the data model
*/
-(NSString*)toJSONString;
- (NSString *)toJSONString;
/**
/**
* Export the whole object to a JSON data text string
* @return JSON text data describing the data model
*/
-(NSData*)toJSONData;
- (NSData *)toJSONData;
/**
* Export the specified properties of the object to a dictionary
* @param propertyNames the properties to export; if nil, all properties exported
* @return dictionary containing the data model
*/
-(NSDictionary*)toDictionaryWithKeys:(NSArray*)propertyNames;
/**
/**
* Export the specified properties of the object to a JSON data text string
* @param propertyNames the properties to export; if nil, all properties exported
* @return JSON text describing the data model
*/
-(NSString*)toJSONStringWithKeys:(NSArray*)propertyNames;
- (NSString *)toJSONStringWithKeys:(NSArray *)propertyNames;
/**
/**
* Export the specified properties of the object to a JSON data text string
* @param propertyNames the properties to export; if nil, all properties exported
* @return JSON text data describing the data model
*/
-(NSData*)toJSONDataWithKeys:(NSArray*)propertyNames;
- (NSData *)toJSONDataWithKeys:(NSArray *)propertyNames;
/** @name Batch methods */
/**
/**
* If you have a list of dictionaries in a JSON feed, you can use this method to create an NSArray
* of model objects. Handy when importing JSON data lists.
* This method will loop over the input list and initialize a data model for every dictionary in the list.
......@@ -227,12 +191,14 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @exception JSONModelInvalidDataException thrown when the input data does not include all required keys
* @see arrayOfDictionariesFromModels:
*/
+(NSMutableArray*)arrayOfModelsFromDictionaries:(NSArray*)array __attribute__((deprecated("use arrayOfModelsFromDictionaries:error:")));
+(NSMutableArray*)arrayOfModelsFromDictionaries:(NSArray*)array error:(NSError**)err;
+(NSMutableArray*)arrayOfModelsFromData:(NSData*)data error:(NSError**)err;
+(NSMutableArray*)arrayOfModelsFromString:(NSString*)string error:(NSError**)err;
+ (NSMutableArray *)arrayOfModelsFromDictionaries:(NSArray *)array error:(NSError **)err;
+ (NSMutableArray *)arrayOfModelsFromData:(NSData *)data error:(NSError **)err;
+ (NSMutableArray *)arrayOfModelsFromString:(NSString *)string error:(NSError **)err;
+ (NSMutableDictionary *)dictionaryOfModelsFromDictionary:(NSDictionary *)dictionary error:(NSError **)err;
+ (NSMutableDictionary *)dictionaryOfModelsFromData:(NSData *)data error:(NSError **)err;
+ (NSMutableDictionary *)dictionaryOfModelsFromString:(NSString *)string error:(NSError **)err;
/**
/**
* If you have an NSArray of data model objects, this method takes it in and outputs a list of the
* matching dictionaries. This method does the opposite of arrayOfObjectsFromDictionaries:
* @param array list of JSONModel objects
......@@ -241,38 +207,12 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* or a property type in your model is not supported by JSONValueTransformer and its categories
* @see arrayOfModelsFromDictionaries:
*/
+(NSMutableArray*)arrayOfDictionariesFromModels:(NSArray*)array;
/** @name Comparing models */
/**
* The name of the model's property, which is considered the model's unique identifier.
* You can define Index property by using the Index protocol:
* @property (strong, nonatomic) NSString&lt;Index&gt;* id;
*/
-(NSString*)indexPropertyName;
/**
* Overridden NSObject method to compare model objects. Compares the &lt;Index&gt; property of the two models,
* if an index property is defined.
* @param object a JSONModel instance to compare to for equality
*/
-(BOOL)isEqual:(id)object;
/**
* Comparison method, which uses the defined &lt;Index&gt; property of the two models, to compare them.
* If there isn't an index property throws an exception. If the Index property does not have a compare: method
* also throws an exception. NSString and NSNumber have compare: methods, and in case the Index property is
* a another custom class, the programmer should create a custom compare: method then.
* @param object a JSONModel instance to compare to
*/
-(NSComparisonResult)compare:(id)object;
+ (NSMutableArray *)arrayOfDictionariesFromModels:(NSArray *)array;
+ (NSMutableDictionary *)dictionaryOfDictionariesFromModels:(NSDictionary *)dictionary;
/** @name Validation */
/**
/**
* Overwrite the validate method in your own models if you need to perform some custom validation over the model data.
* This method gets called at the very end of the JSONModel initializer, thus the model is in the state that you would
* get it back when initialized. Check the values of any property that needs to be validated and if any invalid values
......@@ -284,25 +224,14 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @return a BOOL result, showing whether the model data validates or not. You can use the convenience method
* [JSONModelError errorModelIsInvalid] to set the NSError param if the data fails your custom validation
*/
-(BOOL)validate:(NSError**)error;
- (BOOL)validate:(NSError **)error;
/** @name Key mapping */
/**
* Overwrite in your models if your property names don't match your JSON key names.
* Lookup JSONKeyMapper docs for more details.
*/
+(JSONKeyMapper*)keyMapper;
/**
* Sets a key mapper which affects ALL the models in your project. Use this if you need only one mapper to work
* with your API. For example if you are using the [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase] it is more
* likely that you will need to use it with ALL of your models.
* NB: Custom key mappers take precedence over the global key mapper.
* @param globalKeyMapper a key mapper to apply to all models in your project.
*
* Overwrite in your models if your property names don't match your JSON key names.
* Lookup JSONKeyMapper docs for more details.
*/
+(void)setGlobalKeyMapper:(JSONKeyMapper*)globalKeyMapper;
+ (JSONKeyMapper *)keyMapper;
/**
* Indicates whether the property with the given name is Optional.
......@@ -311,7 +240,7 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @param propertyName the name of the property
* @return a BOOL result indicating whether the property is optional
*/
+(BOOL)propertyIsOptional:(NSString*)propertyName;
+ (BOOL)propertyIsOptional:(NSString *)propertyName;
/**
* Indicates whether the property with the given name is Ignored.
......@@ -320,21 +249,19 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @param propertyName the name of the property
* @return a BOOL result indicating whether the property is ignored
*/
+(BOOL)propertyIsIgnored:(NSString*)propertyName;
+ (BOOL)propertyIsIgnored:(NSString *)propertyName;
/**
* Indicates the protocol name for an array property.
* Indicates the class used for the elements of a collection property.
* Rather than using:
* @property (strong) NSArray<MyType>* things;
* You can implement protocolForArrayProperty: and keep your property
* @property (strong) NSArray <MyType> *things;
* You can implement classForCollectionProperty: and keep your property
* defined like:
* @property (strong) NSArray* things;
* @property (strong) NSArray *things;
* @param propertyName the name of the property
* @return an NSString result indicating the name of the protocol/class
* that should be contained in this array property. Return nil to indicate
* no contained protocol.
* @return Class the class used to deserialize the elements of the collection
*/
+(NSString*)protocolForArrayProperty:(NSString *)propertyName;
+ (Class)classForCollectionProperty:(NSString *)propertyName;
/**
* Merges values from the given dictionary into the model instance.
......@@ -342,7 +269,6 @@ lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
* @param useKeyMapping if YES the method will use the model's key mapper and the global key mapper, if NO
* it'll just try to match the dictionary keys to the model's properties
*/
- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping __attribute__((deprecated("use mergeFromDictionary:useKeyMapping:error:")));
- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error;
- (BOOL)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error;
@end
//
// JSONModel.m
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if !__has_feature(objc_arc)
#error The JSONMOdel framework is ARC only, you can enable ARC on per file basis.
......@@ -25,7 +14,6 @@
#import "JSONModel.h"
#import "JSONModelClassProperty.h"
#import "JSONModelArray.h"
#pragma mark - associated objects names
static const char * kMapperObjectKey;
......@@ -223,7 +211,7 @@ static JSONKeyMapper* globalKeyMapper = nil;
//loop over the required properties list
for (JSONModelClassProperty* property in [self __properties__]) {
transformedName = (keyMapper||globalKeyMapper) ? [self __mapString:property.name withKeyMapper:keyMapper importing:YES] : property.name;
transformedName = (keyMapper||globalKeyMapper) ? [self __mapString:property.name withKeyMapper:keyMapper] : property.name;
//check if exists and if so, add to incoming keys
id value;
......@@ -263,18 +251,18 @@ static JSONKeyMapper* globalKeyMapper = nil;
return YES;
}
-(NSString*)__mapString:(NSString*)string withKeyMapper:(JSONKeyMapper*)keyMapper importing:(BOOL)importing
-(NSString*)__mapString:(NSString*)string withKeyMapper:(JSONKeyMapper*)keyMapper
{
if (keyMapper) {
//custom mapper
NSString* mappedName = [keyMapper convertValue:string isImportingToModel:importing];
NSString* mappedName = [keyMapper convertValue:string];
if (globalKeyMapper && [mappedName isEqualToString: string]) {
mappedName = [globalKeyMapper convertValue:string isImportingToModel:importing];
mappedName = [globalKeyMapper convertValue:string];
}
string = mappedName;
} else if (globalKeyMapper) {
//global keymapper
string = [globalKeyMapper convertValue:string isImportingToModel:importing];
string = [globalKeyMapper convertValue:string];
}
return string;
......@@ -285,8 +273,8 @@ static JSONKeyMapper* globalKeyMapper = nil;
//loop over the incoming keys and set self's properties
for (JSONModelClassProperty* property in [self __properties__]) {
//convert key name ot model keys, if a mapper is provided
NSString* jsonKeyPath = (keyMapper||globalKeyMapper) ? [self __mapString:property.name withKeyMapper:keyMapper importing:YES] : property.name;
//convert key name to model keys, if a mapper is provided
NSString* jsonKeyPath = (keyMapper||globalKeyMapper) ? [self __mapString:property.name withKeyMapper:keyMapper] : property.name;
//JMLog(@"keyPath: %@", jsonKeyPath);
//general check for data type compliance
......@@ -474,12 +462,9 @@ static JSONKeyMapper* globalKeyMapper = nil;
}
} else {
// it's not a JSON data type, and there's no transformer for it
// if property type is not supported - that's a programmer mistake -> exception
@throw [NSException exceptionWithName:@"Type not allowed"
reason:[NSString stringWithFormat:@"%@ type not supported for %@.%@", property.type, [self class], property.name]
userInfo:nil];
NSString* msg = [NSString stringWithFormat:@"%@ type not supported for %@.%@", property.type, [self class], property.name];
JSONModelError* dataErr = [JSONModelError errorInvalidDataWithTypeMismatch:msg];
*err = [dataErr errorByPrependingKeyPathComponent:property.name];
return NO;
}
......@@ -620,15 +605,17 @@ static JSONKeyMapper* globalKeyMapper = nil;
if ([protocolName isEqualToString:@"Optional"]) {
p.isOptional = YES;
} else if([protocolName isEqualToString:@"Index"]) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
p.isIndex = YES;
#pragma GCC diagnostic pop
objc_setAssociatedObject(
self.class,
&kIndexPropertyNameKey,
p.name,
OBJC_ASSOCIATION_RETAIN // This is atomic
);
} else if([protocolName isEqualToString:@"ConvertOnDemand"]) {
p.convertsOnDemand = YES;
} else if([protocolName isEqualToString:@"Ignore"]) {
p = nil;
} else {
......@@ -677,9 +664,9 @@ static JSONKeyMapper* globalKeyMapper = nil;
p = nil;
}
NSString* customProtocol = [[self class] protocolForArrayProperty:nsPropertyName];
if (customProtocol) {
p.protocol = customProtocol;
Class customClass = [[self class] classForCollectionProperty:nsPropertyName];
if (customClass) {
p.protocol = NSStringFromClass(customClass);
}
//few cases where JSONModel will ignore properties automatically
......@@ -691,6 +678,39 @@ static JSONKeyMapper* globalKeyMapper = nil;
if (p && ![propertyIndex objectForKey:p.name]) {
[propertyIndex setValue:p forKey:p.name];
}
// generate custom setters and getter
if (p)
{
NSString *name = [p.name stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[p.name substringToIndex:1].uppercaseString];
// getter
SEL getter = NSSelectorFromString([NSString stringWithFormat:@"JSONObjectFor%@", name]);
if ([self respondsToSelector:getter])
p.customGetter = getter;
// setters
p.customSetters = [NSMutableDictionary new];
SEL genericSetter = NSSelectorFromString([NSString stringWithFormat:@"set%@WithJSONObject:", name]);
if ([self respondsToSelector:genericSetter])
p.customSetters[@"generic"] = [NSValue valueWithBytes:&genericSetter objCType:@encode(SEL)];
for (Class type in allowedJSONTypes)
{
NSString *class = NSStringFromClass([JSONValueTransformer classByResolvingClusterClasses:type]);
if (p.customSetters[class])
continue;
SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@With%@:", name, class]);
if ([self respondsToSelector:setter])
p.customSetters[class] = [NSValue valueWithBytes:&setter objCType:@encode(SEL)];
}
}
}
free(properties);
......@@ -744,11 +764,6 @@ static JSONKeyMapper* globalKeyMapper = nil;
return nil;
}
if (property.convertsOnDemand) {
//on demand conversion
value = [[JSONModelArray alloc] initWithArray:value modelClass:[protocolClass class]];
} else {
//one shot conversion
JSONModelError* arrayErr = nil;
value = [[protocolClass class] arrayOfModelsFromDictionaries:value error:&arrayErr];
......@@ -758,7 +773,6 @@ static JSONKeyMapper* globalKeyMapper = nil;
return nil;
}
}
}
//check if it's a dictionary of models
if ([property.type isSubclassOfClass:[NSDictionary class]]) {
......@@ -835,71 +849,38 @@ static JSONKeyMapper* globalKeyMapper = nil;
}
#pragma mark - custom transformations
-(BOOL)__customSetValue:(id<NSObject>)value forProperty:(JSONModelClassProperty*)property
- (BOOL)__customSetValue:(id <NSObject>)value forProperty:(JSONModelClassProperty *)property
{
if (!property.customSetters)
property.customSetters = [NSMutableDictionary new];
NSString *className = NSStringFromClass([JSONValueTransformer classByResolvingClusterClasses:[value class]]);
NSString *class = NSStringFromClass([JSONValueTransformer classByResolvingClusterClasses:[value class]]);
if (!property.customSetters[className]) {
//check for a custom property setter method
NSString* ucfirstName = [property.name stringByReplacingCharactersInRange:NSMakeRange(0,1)
withString:[[property.name substringToIndex:1] uppercaseString]];
NSString* selectorName = [NSString stringWithFormat:@"set%@With%@:", ucfirstName, className];
SEL setter = nil;
[property.customSetters[class] getValue:&setter];
SEL customPropertySetter = NSSelectorFromString(selectorName);
if (!setter)
[property.customSetters[@"generic"] getValue:&setter];
//check if there's a custom selector like this
if (![self respondsToSelector: customPropertySetter]) {
property.customSetters[className] = [NSNull null];
if (!setter)
return NO;
}
//cache the custom setter selector
property.customSetters[className] = selectorName;
}
IMP imp = [self methodForSelector:setter];
void (*func)(id, SEL, id <NSObject>) = (void *)imp;
func(self, setter, value);
if (property.customSetters[className] != [NSNull null]) {
//call the custom setter
//https://github.com/steipete
SEL selector = NSSelectorFromString(property.customSetters[className]);
((void (*) (id, SEL, id))objc_msgSend)(self, selector, value);
return YES;
}
return NO;
}
-(BOOL)__customGetValue:(id<NSObject>*)value forProperty:(JSONModelClassProperty*)property
- (BOOL)__customGetValue:(id *)value forProperty:(JSONModelClassProperty *)property
{
if (property.getterType == kNotInspected) {
//check for a custom property getter method
NSString* ucfirstName = [property.name stringByReplacingCharactersInRange: NSMakeRange(0,1)
withString: [[property.name substringToIndex:1] uppercaseString]];
NSString* selectorName = [NSString stringWithFormat:@"JSONObjectFor%@", ucfirstName];
SEL customPropertyGetter = NSSelectorFromString(selectorName);
if (![self respondsToSelector: customPropertyGetter]) {
property.getterType = kNo;
SEL getter = property.customGetter;
if (!getter)
return NO;
}
property.getterType = kCustom;
property.customGetter = customPropertyGetter;
IMP imp = [self methodForSelector:getter];
id (*func)(id, SEL) = (void *)imp;
*value = func(self, getter);
}
if (property.getterType==kCustom) {
//call the custom getter
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
*value = [self performSelector:property.customGetter];
#pragma clang diagnostic pop
return YES;
}
return NO;
}
#pragma mark - persistance
......@@ -957,7 +938,7 @@ static JSONKeyMapper* globalKeyMapper = nil;
continue;
//fetch key and value
NSString* keyPath = (self.__keyMapper||globalKeyMapper) ? [self __mapString:p.name withKeyMapper:self.__keyMapper importing:YES] : p.name;
NSString* keyPath = (self.__keyMapper||globalKeyMapper) ? [self __mapString:p.name withKeyMapper:self.__keyMapper] : p.name;
value = [self valueForKey: p.name];
//JMLog(@"toDictionary[%@]->[%@] = '%@'", p.name, keyPath, value);
......@@ -978,7 +959,7 @@ static JSONKeyMapper* globalKeyMapper = nil;
//is still valid if it's to be imported as a model again
if (isNull(value)) {
if (p.isOptional)
if (value == nil)
{
[tempDictionary removeObjectForKey:keyPath];
}
......@@ -1147,6 +1128,49 @@ static JSONKeyMapper* globalKeyMapper = nil;
return list;
}
+ (NSMutableDictionary *)dictionaryOfModelsFromString:(NSString *)string error:(NSError **)err
{
return [self dictionaryOfModelsFromData:[string dataUsingEncoding:NSUTF8StringEncoding] error:err];
}
+ (NSMutableDictionary *)dictionaryOfModelsFromData:(NSData *)data error:(NSError **)err
{
id json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:err];
if (!json || ![json isKindOfClass:[NSDictionary class]]) return nil;
return [self dictionaryOfModelsFromDictionary:json error:err];
}
+ (NSMutableDictionary *)dictionaryOfModelsFromDictionary:(NSDictionary *)dictionary error:(NSError **)err
{
NSMutableDictionary *output = [NSMutableDictionary dictionaryWithCapacity:dictionary.count];
for (NSString *key in dictionary.allKeys)
{
id object = dictionary[key];
if ([object isKindOfClass:NSDictionary.class])
{
id obj = [[self alloc] initWithDictionary:object error:err];
if (obj == nil) return nil;
output[key] = obj;
}
else if ([object isKindOfClass:NSArray.class])
{
id obj = [self arrayOfModelsFromDictionaries:object error:err];
if (obj == nil) return nil;
output[key] = obj;
}
else
{
*err = [JSONModelError errorInvalidDataWithTypeMismatch:@"Only dictionaries and arrays are supported"];
return nil;
}
}
return output;
}
//loop over NSArray of models and export them to JSON objects
+(NSMutableArray*)arrayOfDictionariesFromModels:(NSArray*)array
{
......@@ -1185,7 +1209,27 @@ static JSONKeyMapper* globalKeyMapper = nil;
return list;
}
+(NSMutableDictionary *)dictionaryOfDictionariesFromModels:(NSDictionary *)dictionary
{
//bail early
if (isNull(dictionary)) return nil;
NSMutableDictionary *output = [NSMutableDictionary dictionaryWithCapacity:dictionary.count];
for (NSString *key in dictionary.allKeys) {
id <AbstractJSONModelProtocol> object = dictionary[key];
id obj = [object toDictionary];
if (!obj) return nil;
output[key] = obj;
}
return output;
}
#pragma mark - custom comparison methods
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-(NSString*)indexPropertyName
{
//custom getter for an associated object
......@@ -1236,6 +1280,8 @@ static JSONKeyMapper* globalKeyMapper = nil;
return [super hash];
}
#pragma GCC diagnostic pop
#pragma mark - custom data validation
-(BOOL)validate:(NSError**)error
{
......@@ -1253,7 +1299,7 @@ static JSONKeyMapper* globalKeyMapper = nil;
id value = ([p.name isEqualToString:@"description"])?self->_description:[self valueForKey:p.name];
NSString* valueDescription = (value)?[value description]:@"<nil>";
if (p.isStandardJSONType && ![value respondsToSelector:@selector(count)] && [valueDescription length]>60 && !p.convertsOnDemand) {
if (p.isStandardJSONType && ![value respondsToSelector:@selector(count)] && [valueDescription length]>60) {
//cap description for longer values
valueDescription = [NSString stringWithFormat:@"%@...", [valueDescription substringToIndex:59]];
......@@ -1292,15 +1338,28 @@ static JSONKeyMapper* globalKeyMapper = nil;
return nil;
}
+(Class)classForCollectionProperty:(NSString *)propertyName
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
NSString *protocolName = [self protocolForArrayProperty:propertyName];
#pragma GCC diagnostic pop
if (!protocolName)
return nil;
return NSClassFromString(protocolName);
}
#pragma mark - working with incomplete models
- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping
{
[self mergeFromDictionary:dict useKeyMapping:useKeyMapping error:nil];
}
- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error
- (BOOL)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error
{
[self __importDictionary:dict withKeyMapper:(useKeyMapping)? self.__keyMapper:nil validation:NO error:error];
return [self __importDictionary:dict withKeyMapper:(useKeyMapping)? self.__keyMapper:nil validation:NO error:error];
}
#pragma mark - NSCopying, NSCoding
......@@ -1313,7 +1372,13 @@ static JSONKeyMapper* globalKeyMapper = nil;
-(instancetype)initWithCoder:(NSCoder *)decoder
{
NSString* json = [decoder decodeObjectForKey:@"json"];
NSString* json;
if ([decoder respondsToSelector:@selector(decodeObjectOfClass:forKey:)]) {
json = [decoder decodeObjectOfClass:[NSString class] forKey:@"json"];
} else {
json = [decoder decodeObjectForKey:@"json"];
}
JSONModelError *error = nil;
self = [self initWithString:json error:&error];
......
//
// JSONModelArray.h
//
// @version 0.8.0
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
/**
* **Don't make instances of JSONModelArray yourself, except you know what you are doing.**
*
* You get automatically JSONModelArray instances, when you declare a convert on demand property, like so:
*
* @property (strong, nonatomic) NSArray&lt;JSONModel, ConvertOnDemand&gt;* list;
*
* The class stores its contents as they come from JSON, and upon the first request
* of each of the objects stored in the array, it'll be converted to the target model class.
* Thus saving time upon the very first model creation.
*/
@interface JSONModelArray : NSObject <NSFastEnumeration>
/**
* Don't make instances of JSONModelArray yourself, except you know what you are doing.
*
* @param array an array of NSDictionary objects
* @param cls the JSONModel sub-class you'd like the NSDictionaries to be converted to on demand
*/
- (id)initWithArray:(NSArray *)array modelClass:(Class)cls;
- (id)objectAtIndex:(NSUInteger)index;
- (id)objectAtIndexedSubscript:(NSUInteger)index;
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSUInteger)count;
- (id)firstObject;
- (id)lastObject;
/**
* Looks up the array's contents and tries to find a JSONModel object
* with matching index property value to the indexValue param.
*
* Will return nil if no matching model is found. Will return nil if there's no index property
* defined on the models found in the array (will sample the first object, assuming the array
* contains homogeneous collection of objects)
*
* @param indexValue the id value to search for
* @return the found model or nil
*/
- (id)modelWithIndexValue:(id)indexValue;
@end
//
// JSONModelArray.m
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "JSONModelArray.h"
#import "JSONModel.h"
@implementation JSONModelArray
{
NSMutableArray* _storage;
Class _targetClass;
}
-(id)initWithArray:(NSArray *)array modelClass:(Class)cls
{
self = [super init];
if (self) {
_storage = [NSMutableArray arrayWithArray:array];
_targetClass = cls;
}
return self;
}
-(id)firstObject
{
return [self objectAtIndex:0];
}
-(id)lastObject
{
return [self objectAtIndex:_storage.count - 1];
}
-(id)objectAtIndex:(NSUInteger)index
{
return [self objectAtIndexedSubscript:index];
}
-(id)objectAtIndexedSubscript:(NSUInteger)index
{
id object = _storage[index];
if (![object isMemberOfClass:_targetClass]) {
NSError* err = nil;
object = [[_targetClass alloc] initWithDictionary:object error:&err];
if (object) {
_storage[index] = object;
}
}
return object;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation invokeWithTarget:_storage];
}
-(id)forwardingTargetForSelector:(SEL)selector
{
static NSArray *overriddenMethods = nil;
if (!overriddenMethods) overriddenMethods = @[@"initWithArray:modelClass:", @"objectAtIndex:", @"objectAtIndexedSubscript:", @"count", @"modelWithIndexValue:", @"description", @"mutableCopy", @"firstObject", @"lastObject", @"countByEnumeratingWithState:objects:count:"];
if ([overriddenMethods containsObject:NSStringFromSelector(selector)]) {
return self;
}
return _storage;
}
-(NSUInteger)count
{
return _storage.count;
}
-(id)modelWithIndexValue:(id)indexValue
{
if (self.count==0) return nil;
if (![_storage[0] indexPropertyName]) return nil;
for (JSONModel* model in _storage) {
if ([[model valueForKey:model.indexPropertyName] isEqual:indexValue]) {
return model;
}
}
return nil;
}
-(id)mutableCopy
{
//it's already mutable
return self;
}
#pragma mark - description
-(NSString*)description
{
NSMutableString* res = [NSMutableString stringWithFormat:@"<JSONModelArray[%@]>\n", [_targetClass description]];
for (id m in _storage) {
[res appendString: [m description]];
[res appendString: @",\n"];
}
[res appendFormat:@"\n</JSONModelArray>"];
return res;
}
-(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(id __unsafe_unretained [])stackbuf
count:(NSUInteger)stackbufLength
{
NSUInteger count = 0;
unsigned long countOfItemsAlreadyEnumerated = state->state;
if (countOfItemsAlreadyEnumerated == 0) {
state->mutationsPtr = &state->extra[0];
}
if (countOfItemsAlreadyEnumerated < [self count]) {
state->itemsPtr = stackbuf;
while ((countOfItemsAlreadyEnumerated < [self count]) && (count < stackbufLength)) {
stackbuf[count] = [self objectAtIndex:countOfItemsAlreadyEnumerated];
countOfItemsAlreadyEnumerated++;
count++;
}
} else {
count = 0;
}
state->state = countOfItemsAlreadyEnumerated;
return count;
}
@end
//
// JSONModelClassProperty.h
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
enum kCustomizationTypes {
kNotInspected = 0,
kCustom,
kNo
};
typedef enum kCustomizationTypes PropertyGetterType;
/**
* **You do not need to instantiate this class yourself.** This class is used internally by JSONModel
* to inspect the declared properties of your model class.
......@@ -34,17 +15,20 @@ typedef enum kCustomizationTypes PropertyGetterType;
*/
@interface JSONModelClassProperty : NSObject
// deprecated
@property (assign, nonatomic) BOOL isIndex DEPRECATED_ATTRIBUTE;
/** The name of the declared property (not the ivar name) */
@property (copy, nonatomic) NSString* name;
@property (copy, nonatomic) NSString *name;
/** A property class type */
@property (assign, nonatomic) Class type;
/** Struct name if a struct */
@property (strong, nonatomic) NSString* structName;
@property (strong, nonatomic) NSString *structName;
/** The name of the protocol the property conforms to (or nil) */
@property (copy, nonatomic) NSString* protocol;
@property (copy, nonatomic) NSString *protocol;
/** If YES, it can be missing in the input data, and the input would be still valid */
@property (assign, nonatomic) BOOL isOptional;
......@@ -55,19 +39,10 @@ typedef enum kCustomizationTypes PropertyGetterType;
/** If YES - create a mutable object for the value of the property */
@property (assign, nonatomic) BOOL isMutable;
/** If YES - create models on demand for the array members */
@property (assign, nonatomic) BOOL convertsOnDemand;
/** If YES - the value of this property determines equality to other models */
@property (assign, nonatomic) BOOL isIndex;
/** The status of property getter introspection in a model */
@property (assign, nonatomic) PropertyGetterType getterType;
/** a custom getter for this property, found in the owning model */
@property (assign, nonatomic) SEL customGetter;
/** custom setters for this property, found in the owning model */
@property (strong, nonatomic) NSMutableDictionary<NSString *, id> *customSetters;
@property (strong, nonatomic) NSMutableDictionary *customSetters;
@end
//
// JSONModelClassProperty.m
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "JSONModelClassProperty.h"
......@@ -23,10 +12,13 @@
//build the properties string for the current class property
NSMutableArray* properties = [NSMutableArray arrayWithCapacity:8];
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
if (self.isIndex) [properties addObject:@"Index"];
#pragma GCC diagnostic pop
if (self.isOptional) [properties addObject:@"Optional"];
if (self.isMutable) [properties addObject:@"Mutable"];
if (self.convertsOnDemand) [properties addObject:@"ConvertOnDemand"];
if (self.isStandardJSONType) [properties addObject:@"Standard JSON type"];
if (self.customGetter) [properties addObject:[NSString stringWithFormat: @"Getter = %@", NSStringFromSelector(self.customGetter)]];
......@@ -36,8 +28,9 @@
for (id obj in self.customSetters.allValues)
{
if (obj != [NSNull null])
[setters addObject:obj];
SEL selector;
[obj getValue:&selector];
[setters addObject:NSStringFromSelector(selector)];
}
[properties addObject:[NSString stringWithFormat: @"Setters = [%@]", [setters componentsJoinedByString:@", "]]];
......
//
// JSONModelError.h
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
......@@ -28,7 +17,7 @@ typedef NS_ENUM(int, kJSONModelErrorTypes)
/////////////////////////////////////////////////////////////////////////////////////////////
/** The domain name used for the JSONModelError instances */
extern NSString* const JSONModelErrorDomain;
extern NSString *const JSONModelErrorDomain;
/**
* If the model JSON input misses keys that are required, check the
......@@ -36,7 +25,7 @@ extern NSString* const JSONModelErrorDomain;
* under the kJSONModelMissingKeys key you will find a list of the
* names of the missing keys.
*/
extern NSString* const kJSONModelMissingKeys;
extern NSString *const kJSONModelMissingKeys;
/**
* If JSON input has a different type than expected by the model, check the
......@@ -44,14 +33,14 @@ extern NSString* const kJSONModelMissingKeys;
* under the kJSONModelTypeMismatch key you will find a description
* of the mismatched types.
*/
extern NSString* const kJSONModelTypeMismatch;
extern NSString *const kJSONModelTypeMismatch;
/**
* If an error occurs in a nested model, check the userInfo dictionary of
* the JSONModelError instance you get back - under the kJSONModelKeyPath
* key you will find key-path at which the error occurred.
*/
extern NSString* const kJSONModelKeyPath;
extern NSString *const kJSONModelKeyPath;
/////////////////////////////////////////////////////////////////////////////////////////////
/**
......@@ -60,46 +49,46 @@ extern NSString* const kJSONModelKeyPath;
*/
@interface JSONModelError : NSError
@property (strong, nonatomic) NSHTTPURLResponse* httpResponse;
@property (strong, nonatomic) NSHTTPURLResponse *httpResponse;
@property (strong, nonatomic) NSData* responseData;
@property (strong, nonatomic) NSData *responseData;
/**
* Creates a JSONModelError instance with code kJSONModelErrorInvalidData = 1
*/
+(id)errorInvalidDataWithMessage:(NSString*)message;
+ (id)errorInvalidDataWithMessage:(NSString *)message;
/**
* Creates a JSONModelError instance with code kJSONModelErrorInvalidData = 1
* @param keys a set of field names that were required, but not found in the input
*/
+(id)errorInvalidDataWithMissingKeys:(NSSet*)keys;
+ (id)errorInvalidDataWithMissingKeys:(NSSet *)keys;
/**
* Creates a JSONModelError instance with code kJSONModelErrorInvalidData = 1
* @param mismatchDescription description of the type mismatch that was encountered.
*/
+(id)errorInvalidDataWithTypeMismatch:(NSString*)mismatchDescription;
+ (id)errorInvalidDataWithTypeMismatch:(NSString *)mismatchDescription;
/**
* Creates a JSONModelError instance with code kJSONModelErrorBadResponse = 2
*/
+(id)errorBadResponse;
+ (id)errorBadResponse;
/**
* Creates a JSONModelError instance with code kJSONModelErrorBadJSON = 3
*/
+(id)errorBadJSON;
+ (id)errorBadJSON;
/**
* Creates a JSONModelError instance with code kJSONModelErrorModelIsInvalid = 4
*/
+(id)errorModelIsInvalid;
+ (id)errorModelIsInvalid;
/**
* Creates a JSONModelError instance with code kJSONModelErrorNilInput = 5
*/
+(id)errorInputIsNil;
+ (id)errorInputIsNil;
/**
* Creates a new JSONModelError with the same values plus information about the key-path of the error.
......@@ -108,7 +97,7 @@ extern NSString* const kJSONModelKeyPath;
* This key contains the component string parameter. If the key is already present
* then the new error object has the component string prepended to the existing value.
*/
- (instancetype)errorByPrependingKeyPathComponent:(NSString*)component;
- (instancetype)errorByPrependingKeyPathComponent:(NSString *)component;
/////////////////////////////////////////////////////////////////////////////////////////////
@end
//
// JSONModelError.m
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "JSONModelError.h"
......
//
// NSArray+JSONModel.h
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import "JSONModel.h"
/**
* Exposes invisible JSONModelArray methods
*/
@interface NSArray(JSONModel)
/**
* Looks up the array's contents and tries to find a JSONModel object
* with matching index property value to the indexValue param.
*
* Will return nil if no matching model is found. Will return nil if there's no index property
* defined on the models found in the array (will sample the first object, assuming the array
* contains homogeneous collection of objects)
*
* @param indexValue the id value to search for
* @return the found model or nil
* @exception NSException throws exception if you call this method on an instance, which is not actually a JSONModelArray
*/
- (id)modelWithIndexValue:(id)indexValue;
@end
//
// NSArray+JSONModel.m
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "NSArray+JSONModel.h"
@implementation NSArray(JSONModel)
- (id)modelWithIndexValue:(id)indexValue
{
NSAssert(NO, @"call modelWithIndexValue: on a ConvertOnDemand property, which is defined like that: @property (strong, nonatomic) NSArray<MyModel, ConvertOnDemand>* list;");
return nil;
}
@end
//
// JSONModelLib.h
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
//JSONModel transformations
// core
#import "JSONModel.h"
#import "JSONModelError.h"
// transformations
#import "JSONValueTransformer.h"
#import "JSONKeyMapper.h"
//basic JSONModel classes
#import "JSONModelError.h"
#import "JSONModelClassProperty.h"
#import "JSONModel.h"
//network classes
// networking (deprecated)
#import "JSONHTTPClient.h"
#import "JSONModel+networking.h"
#import "JSONAPI.h"
//models array
#import "NSArray+JSONModel.h"
#import "JSONModelArray.h"
//
// JSONAPI.h
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// JSONModel
//
#import <Foundation/Foundation.h>
#import "JSONHTTPClient.h"
/////////////////////////////////////////////////////////////////////////////////////////////
/**
* @discussion Class for working with JSON APIs. It builds upon the JSONHTTPClient class
* and facilitates making requests to the same web host. Also features helper
* method for making calls to a JSON RPC service
*/
DEPRECATED_ATTRIBUTE
@interface JSONAPI : NSObject
/////////////////////////////////////////////////////////////////////////////////////////////
/** @name Configuring the API */
/**
* Sets the API url
* @param base the API url as a string
*/
+(void)setAPIBaseURLWithString:(NSString*)base;
/**
* Sets the default content type for the requests/responses
* @param ctype The content-type as a string. Some possible types,
* depending on the service: application/json, text/json, x-application/javascript, etc.
*/
+(void)setContentType:(NSString*)ctype;
/////////////////////////////////////////////////////////////////////////////////////////////
/** @name Making GET API requests */
/**
* Makes an asynchronous GET request to the API
* @param path the URL path to add to the base API URL for this HTTP call
* @param params the variables to pass to the API
* @param completeBlock a JSONObjectBlock block to execute upon completion
*/
+(void)getWithPath:(NSString*)path andParams:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock;
/////////////////////////////////////////////////////////////////////////////////////////////
/** @name Making POST API requests */
/**
* Makes a POST request to the API
* @param path the URL path to add to the base API URL for this HTTP call
* @param params the variables to pass to the API
* @param completeBlock a JSONObjectBlock block to execute upon completion
*/
+(void)postWithPath:(NSString*)path andParams:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock;
/////////////////////////////////////////////////////////////////////////////////////////////
/** @name JSON RPC methods */
/**
* Makes an asynchronous JSON RPC request to the API. Read more: http://www.jsonrpc.org
* @param method the HTTP method name; GET or POST only
* @param args the list of arguments to pass to the API
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)rpcWithMethodName:(NSString*)method andArguments:(NSArray*)args completion:(JSONObjectBlock)completeBlock;
/** @name JSON RPC (2.0) request method */
/**
* Makes an asynchronous JSON RPC 2.0 request to the API. Read more: http://www.jsonrpc.org
* @param method the HTTP method name; GET or POST only
* @param params the params to pass to the API - an NSArray or an NSDictionary,
* depending whether you're using named or unnamed parameters
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)rpc2WithMethodName:(NSString*)method andParams:(id)params completion:(JSONObjectBlock)completeBlock;
/////////////////////////////////////////////////////////////////////////////////////////////
+ (void)setAPIBaseURLWithString:(NSString *)base DEPRECATED_ATTRIBUTE;
+ (void)setContentType:(NSString *)ctype DEPRECATED_ATTRIBUTE;
+ (void)getWithPath:(NSString *)path andParams:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)postWithPath:(NSString *)path andParams:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)rpcWithMethodName:(NSString *)method andArguments:(NSArray *)args completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)rpc2WithMethodName:(NSString *)method andParams:(id)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
@end
//
// JSONAPI.m
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// JSONModel
//
#import "JSONAPI.h"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
#pragma mark - helper error model class
@interface JSONAPIRPCErrorModel: JSONModel
@property (assign, nonatomic) int code;
......@@ -26,6 +18,7 @@
#pragma mark - static variables
static JSONAPI* sharedInstance = nil;
static long jsonRpcId = 0;
#pragma mark - JSONAPI() private interface
......
//
// JSONModelHTTPClient.h
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// JSONModel
//
#import "JSONModel.h"
#pragma mark - definitions
/**
* HTTP Request methods
*/
extern NSString* const kHTTPMethodGET;
extern NSString* const kHTTPMethodPOST;
/**
* Content-type strings
*/
extern NSString* const kContentTypeAutomatic;
extern NSString* const kContentTypeJSON;
extern NSString* const kContentTypeWWWEncoded;
extern NSString *const kHTTPMethodGET DEPRECATED_ATTRIBUTE;
extern NSString *const kHTTPMethodPOST DEPRECATED_ATTRIBUTE;
extern NSString *const kContentTypeAutomatic DEPRECATED_ATTRIBUTE;
extern NSString *const kContentTypeJSON DEPRECATED_ATTRIBUTE;
extern NSString *const kContentTypeWWWEncoded DEPRECATED_ATTRIBUTE;
/**
* A block type to handle incoming JSON object and an error.
* You pass it to methods which fetch JSON asynchronously. When the operation is finished
* you receive back the fetched JSON (or nil) and an error (or nil)
*
* @param json object derived from a JSON string
* @param err JSONModelError or nil
*/
typedef void (^JSONObjectBlock)(id json, JSONModelError* err);
typedef void (^JSONObjectBlock)(id json, JSONModelError *err) DEPRECATED_ATTRIBUTE;
/////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - configuration methods
/**
* @discussion A very thin HTTP client that can do GET and POST HTTP requests.
* It fetches only JSON data and also deserializes it using NSJSONSerialization.
*/
DEPRECATED_ATTRIBUTE
@interface JSONHTTPClient : NSObject
/////////////////////////////////////////////////////////////////////////////////////////////
/** @name HTTP Client configuration */
/**
* Returns a modifiable dictionary of the client's default HTTP headers.
* @result A mutable dictionary of pairs - HTTP header names and values.
* @discussion You can use the result to modify the http client headers like so:
* <pre>
* NSMutableDictionary* headers = [JSONHTTPClient requestHeaders];
* headers[@"APIToken"] = @"MySecretTokenValue";
* </pre>
*/
+(NSMutableDictionary*)requestHeaders;
/**
* Sets the default encoding of the request body.
* See NSStringEncoding for a list of supported encodings
* @param encoding text encoding constant
*/
+(void)setDefaultTextEncoding:(NSStringEncoding)encoding;
/**
* Sets the policies for caching HTTP data
* See NSURLRequestCachePolicy for a list of the pre-defined policies
* @param policy the caching policy
*/
+(void)setCachingPolicy:(NSURLRequestCachePolicy)policy;
/**
* Sets the timeout for network calls
* @param seconds the amount of seconds to wait before considering the call failed
*/
+(void)setTimeoutInSeconds:(int)seconds;
/**
* A method to set the default content type of the request body
* By default the content type is set to kContentTypeAutomatic
* which checks the body request and decides between "application/json"
* and "application/x-www-form-urlencoded"
*/
+(void)setRequestContentType:(NSString*)contentTypeString;
/////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - GET asynchronous JSON calls
/** @name Making asynchronous HTTP requests */
/**
* Makes GET request to the given URL address and fetches a JSON response.
* @param urlString the URL as a string
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)getJSONFromURLWithString:(NSString*)urlString completion:(JSONObjectBlock)completeBlock;
/**
* Makes GET request to the given URL address and fetches a JSON response. Sends the params as a query string variables.
* @param urlString the URL as a string
* @param params a dictionary of key / value pairs to be send as variables to the request
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)getJSONFromURLWithString:(NSString*)urlString params:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock;
/**
* Makes a request to the given URL address and fetches a JSON response.
* @param urlString the URL as a string
* @param method the method of the request as a string
* @param params a dictionary of key / value pairs to be send as variables to the request
* @param bodyString the body of the POST request as a string
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)JSONFromURLWithString:(NSString*)urlString method:(NSString*)method params:(NSDictionary*)params orBodyString:(NSString*)bodyString completion:(JSONObjectBlock)completeBlock;
/**
* Makes a request to the given URL address and fetches a JSON response.
* @param urlString the URL as a string
* @param method the method of the request as a string
* @param params a dictionary of key / value pairs to be send as variables to the request
* @param bodyString the body of the POST request as a string
* @param headers the headers to set on the request - overrides those in +requestHeaders
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)JSONFromURLWithString:(NSString*)urlString method:(NSString*)method params:(NSDictionary*)params orBodyString:(NSString*)bodyString headers:(NSDictionary*)headers completion:(JSONObjectBlock)completeBlock;
/**
* Makes a request to the given URL address and fetches a JSON response.
* @param urlString the URL as a string
* @param method the method of the request as a string
* @param params a dictionary of key / value pairs to be send as variables to the request
* @param bodyData the body of the POST request as raw binary data
* @param headers the headers to set on the request - overrides those in +requestHeaders
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)JSONFromURLWithString:(NSString*)urlString method:(NSString*)method params:(NSDictionary *)params orBodyData:(NSData*)bodyData headers:(NSDictionary*)headers completion:(JSONObjectBlock)completeBlock;
/////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - POST asynchronous JSON calls
/**
* Makes POST request to the given URL address and fetches a JSON response. Sends the bodyString param as the POST request body.
* @param urlString the URL as a string
* @param params a dictionary of key / value pairs to be send as variables to the request
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)postJSONFromURLWithString:(NSString*)urlString params:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock;
/**
* Makes POST request to the given URL address and fetches a JSON response. Sends the bodyString param as the POST request body.
* @param urlString the URL as a string
* @param bodyString the body of the POST request as a string
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)postJSONFromURLWithString:(NSString*)urlString bodyString:(NSString*)bodyString completion:(JSONObjectBlock)completeBlock;
/**
* Makes POST request to the given URL address and fetches a JSON response. Sends the bodyString param as the POST request body.
* @param urlString the URL as a string
* @param bodyData the body of the POST request as an NSData object
* @param completeBlock JSONObjectBlock to execute upon completion
*/
+(void)postJSONFromURLWithString:(NSString*)urlString bodyData:(NSData*)bodyData completion:(JSONObjectBlock)completeBlock;
+ (NSMutableDictionary *)requestHeaders DEPRECATED_ATTRIBUTE;
+ (void)setDefaultTextEncoding:(NSStringEncoding)encoding DEPRECATED_ATTRIBUTE;
+ (void)setCachingPolicy:(NSURLRequestCachePolicy)policy DEPRECATED_ATTRIBUTE;
+ (void)setTimeoutInSeconds:(int)seconds DEPRECATED_ATTRIBUTE;
+ (void)setRequestContentType:(NSString *)contentTypeString DEPRECATED_ATTRIBUTE;
+ (void)getJSONFromURLWithString:(NSString *)urlString completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)getJSONFromURLWithString:(NSString *)urlString params:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyString:(NSString *)bodyString completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyString:(NSString *)bodyString headers:(NSDictionary *)headers completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyData:(NSData *)bodyData headers:(NSDictionary *)headers completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)postJSONFromURLWithString:(NSString *)urlString params:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)postJSONFromURLWithString:(NSString *)urlString bodyString:(NSString *)bodyString completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)postJSONFromURLWithString:(NSString *)urlString bodyData:(NSData *)bodyData completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE;
@end
//
// JSONModelHTTPClient.m
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "JSONHTTPClient.h"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
typedef void (^RequestResultBlock)(NSData *data, JSONModelError *error);
#pragma mark - constants
......
//
// JSONModel+networking.h
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// JSONModel
//
#import "JSONModel.h"
#import "JSONHTTPClient.h"
typedef void (^JSONModelBlock)(id model, JSONModelError* err);
/**
* The JSONModel(networking) class category adds networking to JSONModel.
* It adds initFromURLWithString: initializer, which makes a GET http request
* to the URL given and initializes the model with the returned JSON.
* Use #import "JSONModel+networking.h" to import networking capabilities.
*/
@interface JSONModel(Networking)
@property (assign, nonatomic) BOOL isLoading;
/** @name Asynchronously create a model over the network */
/**
* Asynchronously create a model over the network. Create a new model instance and initialize it with the JSON fetched from the given URL
* @param urlString the absolute URL address of the JSON feed as a string
* @param completeBlock JSONModelBlock executed upon completion. The JSONModelBlock type is defined as: void (^JSONModelBlock)(JSONModel* model, JSONModelError* e); the first parameter is the initialized model or nil,
* and second parameter holds the model initialization error, if any
*/
-(instancetype)initFromURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock;
/**
* Asynchronously gets the contents of a URL and constructs a JSONModel object from the response.
* The constructed JSONModel object passed as the first parameter to the completion block will be of the same
* class as the receiver. So call this method on yourJSONModel sub-class rather than directly on JSONModel.
* @param urlString The absolute URL of the JSON resource, as a string
* @param completeBlock The block to be called upon completion.
* JSONModelBlock type is defined as: void (^JSONModelBlock)(JSONModel* model, JSONModelError* err);
* The first parameter is the initialized model (of the same JSONModel sub-class as the receiver) or nil if there was an error;
* The second parameter is the initialization error, if any.
*/
+ (void)getModelFromURLWithString:(NSString*)urlString completion:(JSONModelBlock)completeBlock;
typedef void (^JSONModelBlock)(id model, JSONModelError *err) DEPRECATED_ATTRIBUTE;
/**
* Asynchronously posts a JSONModel object (as JSON) to a URL and constructs a JSONModel object from the response.
* The constructed JSONModel object passed as the first parameter to the completion block will be of the same
* class as the receiver. So call this method on yourJSONModel sub-class rather than directly on JSONModel.
* @param post A JSONModel object that will be converted to JSON and sent as the POST data to the HTTP request.
* @param urlString The absolute URL of the JSON resource, as a string
* @param completeBlock The block to be called upon completion.
* JSONModelBlock type is defined as: void (^JSONModelBlock)(JSONModel* model, JSONModelError* err);
* The first parameter is the initialized model (of the same JSONModel sub-class as the receiver) or nil if there was an error;
* The second parameter is the initialization error, if any.
*/
+ (void)postModel:(JSONModel*)post toURLWithString:(NSString*)urlString completion:(JSONModelBlock)completeBlock;
@interface JSONModel (Networking)
@property (assign, nonatomic) BOOL isLoading DEPRECATED_ATTRIBUTE;
- (instancetype)initFromURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)getModelFromURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock DEPRECATED_ATTRIBUTE;
+ (void)postModel:(JSONModel *)post toURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock DEPRECATED_ATTRIBUTE;
@end
//
// JSONModel+networking.m
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "JSONModel+networking.h"
#import "JSONHTTPClient.h"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
BOOL _isLoading;
@implementation JSONModel(Networking)
......
//
// JSONKeyMapper.h
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
typedef NSString* (^JSONModelKeyMapBlock)(NSString* keyName);
typedef NSString *(^JSONModelKeyMapBlock)(NSString *keyName);
/**
* **You won't need to create or store instances of this class yourself.** If you want your model
......@@ -32,71 +21,76 @@ typedef NSString* (^JSONModelKeyMapBlock)(NSString* keyName);
* To comply with Obj-C accepted camelCase property naming for your classes,
* you need to provide mapping between JSON keys and ObjC property names.
*
* In your model overwrite the +(JSONKeyMapper*)keyMapper method and provide a JSONKeyMapper
* In your model overwrite the + (JSONKeyMapper *)keyMapper method and provide a JSONKeyMapper
* instance to convert the key names for your model.
*
* If you need custom mapping it's as easy as:
* <pre>
* +(JSONKeyMapper*)keyMapper {
* + (JSONKeyMapper *)keyMapper {
* &nbsp; return [[JSONKeyMapper&nbsp;alloc]&nbsp;initWithDictionary:@{@"crazy_JSON_name":@"myCamelCaseName"}];
* }
* </pre>
* In case you want to handle underscore_case, **use the predefined key mapper**, like so:
* <pre>
* +(JSONKeyMapper*)keyMapper {
* + (JSONKeyMapper *)keyMapper {
* &nbsp; return [JSONKeyMapper&nbsp;mapperFromUnderscoreCaseToCamelCase];
* }
* </pre>
*/
@interface JSONKeyMapper : NSObject
/** @name Name converters */
/** Block, which takes in a JSON key and converts it to the corresponding property name */
@property (readonly, nonatomic) JSONModelKeyMapBlock JSONToModelKeyBlock;
// deprecated
@property (readonly, nonatomic) JSONModelKeyMapBlock JSONToModelKeyBlock DEPRECATED_ATTRIBUTE;
- (NSString *)convertValue:(NSString *)value isImportingToModel:(BOOL)importing DEPRECATED_MSG_ATTRIBUTE("use convertValue:");
- (instancetype)initWithDictionary:(NSDictionary *)map DEPRECATED_MSG_ATTRIBUTE("use initWithModelToJSONDictionary:");
- (instancetype)initWithJSONToModelBlock:(JSONModelKeyMapBlock)toModel modelToJSONBlock:(JSONModelKeyMapBlock)toJSON DEPRECATED_MSG_ATTRIBUTE("use initWithModelToJSONBlock:");
+ (instancetype)mapper:(JSONKeyMapper *)baseKeyMapper withExceptions:(NSDictionary *)exceptions DEPRECATED_MSG_ATTRIBUTE("use baseMapper:withModelToJSONExceptions:");
+ (instancetype)mapperFromUnderscoreCaseToCamelCase DEPRECATED_MSG_ATTRIBUTE("use mapperForSnakeCase:");
+ (instancetype)mapperFromUpperCaseToLowerCase DEPRECATED_ATTRIBUTE;
/** @name Name converters */
/** Block, which takes in a property name and converts it to the corresponding JSON key name */
@property (readonly, nonatomic) JSONModelKeyMapBlock modelToJSONKeyBlock;
/** Combined converter method
* @param value the source name
* @param importing YES invokes JSONToModelKeyBlock, NO - modelToJSONKeyBlock
* @return JSONKeyMapper instance
*/
-(NSString*)convertValue:(NSString*)value isImportingToModel:(BOOL)importing;
* @param value the source name
* @return JSONKeyMapper instance
*/
- (NSString *)convertValue:(NSString *)value;
/** @name Creating a key mapper */
/**
* Creates a JSONKeyMapper instance, based on the two blocks you provide this initializer.
* The two parameters take in a JSONModelKeyMapBlock block:
* <pre>NSString* (^JSONModelKeyMapBlock)(NSString* keyName)</pre>
* Creates a JSONKeyMapper instance, based on the block you provide this initializer.
* The parameter takes in a JSONModelKeyMapBlock block:
* <pre>NSString *(^JSONModelKeyMapBlock)(NSString *keyName)</pre>
* The block takes in a string and returns the transformed (if at all) string.
* @param toModel transforms JSON key name to your model property name
* @param toJSON transforms your model property name to a JSON key
*/
-(instancetype)initWithJSONToModelBlock:(JSONModelKeyMapBlock)toModel
modelToJSONBlock:(JSONModelKeyMapBlock)toJSON;
- (instancetype)initWithModelToJSONBlock:(JSONModelKeyMapBlock)toJSON;
/**
* Creates a JSONKeyMapper instance, based on the mapping you provide
* in the map parameter. Use the JSON key names as keys, your JSONModel
* property names as values.
* @param map map dictionary, in the format: <pre>@{@"crazy_JSON_name":@"myCamelCaseName"}</pre>
* Creates a JSONKeyMapper instance, based on the mapping you provide.
* Use your JSONModel property names as keys, and the JSON key names as values.
* @param toJSON map dictionary, in the format: <pre>@{@"myCamelCaseName":@"crazy_JSON_name"}</pre>
* @return JSONKeyMapper instance
*/
-(instancetype)initWithDictionary:(NSDictionary*)map;
- (instancetype)initWithModelToJSONDictionary:(NSDictionary *)toJSON;
/**
* Creates a JSONKeyMapper, which converts underscore_case to camelCase and vice versa.
* Given a camelCase model property, this mapper finds JSON keys using the snake_case equivalent.
*/
+(instancetype)mapperFromUnderscoreCaseToCamelCase;
+ (instancetype)mapperForSnakeCase;
+(instancetype)mapperFromUpperCaseToLowerCase;
/**
* Given a camelCase model property, this mapper finds JSON keys using the TitleCase equivalent.
*/
+ (instancetype)mapperForTitleCase;
/**
* Creates a JSONKeyMapper based on a built-in JSONKeyMapper, with specific exceptions.
* Use the original JSON key names as keys, and your JSONModel property names as values.
* Use your JSONModel property names as keys, and the JSON key names as values.
*/
+ (instancetype)mapper:(JSONKeyMapper *)baseKeyMapper withExceptions:(NSDictionary *)exceptions;
+ (instancetype)baseMapper:(JSONKeyMapper *)baseKeyMapper withModelToJSONExceptions:(NSDictionary *)toJSON;
@end
//
// JSONKeyMapper.m
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "JSONKeyMapper.h"
#import <libkern/OSAtomic.h>
@interface JSONKeyMapper()
@property (nonatomic, strong) NSMutableDictionary *toModelMap;
@property (nonatomic, strong) NSMutableDictionary *toJSONMap;
@property (nonatomic, assign) OSSpinLock lock;
@end
@implementation JSONKeyMapper
-(instancetype)init
- (instancetype)init
{
self = [super init];
if (self) {
//initialization
self.toModelMap = [NSMutableDictionary dictionary];
self.toJSONMap = [NSMutableDictionary dictionary];
}
if (!(self = [super init]))
return nil;
_toJSONMap = [NSMutableDictionary new];
return self;
}
-(instancetype)initWithJSONToModelBlock:(JSONModelKeyMapBlock)toModel
modelToJSONBlock:(JSONModelKeyMapBlock)toJSON
- (instancetype)initWithJSONToModelBlock:(JSONModelKeyMapBlock)toModel modelToJSONBlock:(JSONModelKeyMapBlock)toJSON
{
self = [self init];
if (self) {
__weak JSONKeyMapper* weakSelf = self;
_JSONToModelKeyBlock = [^NSString* (NSString* keyName) {
__strong JSONKeyMapper* strongSelf = weakSelf;
//try to return cached transformed key
if (strongSelf.toModelMap[keyName]) {
return strongSelf.toModelMap[keyName];
}
//try to convert the key, and store in the cache
NSString* result = toModel(keyName);
return [self initWithModelToJSONBlock:toJSON];
}
OSSpinLockLock(&strongSelf->_lock);
strongSelf.toModelMap[keyName] = result;
OSSpinLockUnlock(&strongSelf->_lock);
- (instancetype)initWithModelToJSONBlock:(JSONModelKeyMapBlock)toJSON
{
if (!(self = [self init]))
return nil;
return result;
__weak JSONKeyMapper *weakSelf = self;
} copy];
_modelToJSONKeyBlock = ^NSString *(NSString *keyName)
{
__strong JSONKeyMapper *strongSelf = weakSelf;
_modelToJSONKeyBlock = [^NSString* (NSString* keyName) {
id cached = strongSelf.toJSONMap[keyName];
__strong JSONKeyMapper *strongSelf = weakSelf;
if (cached == [NSNull null])
return nil;
//try to return cached transformed key
if (strongSelf.toJSONMap[keyName]) {
if (cached)
return strongSelf.toJSONMap[keyName];
}
//try to convert the key, and store in the cache
NSString* result = toJSON(keyName);
NSString *result = toJSON(keyName);
OSSpinLockLock(&strongSelf->_lock);
strongSelf.toJSONMap[keyName] = result;
strongSelf.toJSONMap[keyName] = result ? result : [NSNull null];
OSSpinLockUnlock(&strongSelf->_lock);
return result;
} copy];
}
};
return self;
}
-(instancetype)initWithDictionary:(NSDictionary *)map
- (instancetype)initWithDictionary:(NSDictionary *)map
{
self = [super init];
if (self) {
NSDictionary *toJSON = [JSONKeyMapper swapKeysAndValuesInDictionary:map];
NSDictionary *userToModelMap = [map copy];
NSDictionary *userToJSONMap = [self swapKeysAndValuesInDictionary:map];
return [self initWithModelToJSONDictionary:toJSON];
}
_JSONToModelKeyBlock = ^NSString *(NSString *keyName) {
NSString *result = [userToModelMap valueForKeyPath:keyName];
return result ? result : keyName;
};
- (instancetype)initWithModelToJSONDictionary:(NSDictionary *)toJSON
{
if (!(self = [super init]))
return nil;
_modelToJSONKeyBlock = ^NSString *(NSString *keyName) {
NSString *result = [userToJSONMap valueForKeyPath:keyName];
return result ? result : keyName;
_modelToJSONKeyBlock = ^NSString *(NSString *keyName)
{
return [toJSON valueForKeyPath:keyName] ?: keyName;
};
}
return self;
}
- (NSDictionary *)swapKeysAndValuesInDictionary:(NSDictionary *)dictionary
+ (NSDictionary *)swapKeysAndValuesInDictionary:(NSDictionary *)dictionary
{
NSMutableDictionary *swapped = [NSMutableDictionary new];
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
NSAssert([value isKindOfClass:[NSString class]], @"Expect keys and values to be NSString");
NSAssert([key isKindOfClass:[NSString class]], @"Expect keys and values to be NSString");
swapped[value] = key;
}];
NSArray *keys = dictionary.allKeys;
NSArray *values = [dictionary objectsForKeys:keys notFoundMarker:[NSNull null]];
return swapped;
return [NSDictionary dictionaryWithObjects:keys forKeys:values];
}
-(NSString*)convertValue:(NSString*)value isImportingToModel:(BOOL)importing
- (NSString *)convertValue:(NSString *)value isImportingToModel:(BOOL)importing
{
return !importing?_JSONToModelKeyBlock(value):_modelToJSONKeyBlock(value);
return [self convertValue:value];
}
+(instancetype)mapperFromUnderscoreCaseToCamelCase
- (NSString *)convertValue:(NSString *)value
{
JSONModelKeyMapBlock toModel = ^ NSString* (NSString* keyName) {
//bail early if no transformation required
if ([keyName rangeOfString:@"_"].location==NSNotFound) return keyName;
//derive camel case out of underscore case
NSString* camelCase = [keyName capitalizedString];
camelCase = [camelCase stringByReplacingOccurrencesOfString:@"_" withString:@""];
camelCase = [camelCase stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[camelCase substringToIndex:1] lowercaseString] ];
return camelCase;
};
JSONModelKeyMapBlock toJSON = ^ NSString* (NSString* keyName) {
NSMutableString* result = [NSMutableString stringWithString:keyName];
NSRange upperCharRange = [result rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]];
return _modelToJSONKeyBlock(value);
}
//handle upper case chars
while ( upperCharRange.location!=NSNotFound) {
+ (instancetype)mapperFromUnderscoreCaseToCamelCase
{
return [self mapperForSnakeCase];
}
NSString* lowerChar = [[result substringWithRange:upperCharRange] lowercaseString];
[result replaceCharactersInRange:upperCharRange
withString:[NSString stringWithFormat:@"_%@", lowerChar]];
upperCharRange = [result rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]];
+ (instancetype)mapperForSnakeCase
{
return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName)
{
NSMutableString *result = [NSMutableString stringWithString:keyName];
NSRange range;
// handle upper case chars
range = [result rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]];
while (range.location != NSNotFound)
{
NSString *lower = [result substringWithRange:range].lowercaseString;
[result replaceCharactersInRange:range withString:[NSString stringWithFormat:@"_%@", lower]];
range = [result rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]];
}
//handle numbers
NSRange digitsRange = [result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
while ( digitsRange.location!=NSNotFound) {
// handle numbers
range = [result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
while (range.location != NSNotFound)
{
NSRange end = [result rangeOfString:@"\\D" options:NSRegularExpressionSearch range:NSMakeRange(range.location, result.length - range.location)];
NSRange digitsRangeEnd = [result rangeOfString:@"\\D" options:NSRegularExpressionSearch range:NSMakeRange(digitsRange.location, result.length-digitsRange.location)];
if (digitsRangeEnd.location == NSNotFound) {
//spands till the end of the key name
digitsRangeEnd = NSMakeRange(result.length, 1);
}
NSRange replaceRange = NSMakeRange(digitsRange.location, digitsRangeEnd.location - digitsRange.location);
NSString* digits = [result substringWithRange:replaceRange];
// spans to the end of the key name
if (end.location == NSNotFound)
end = NSMakeRange(result.length, 1);
NSRange replaceRange = NSMakeRange(range.location, end.location - range.location);
NSString *digits = [result substringWithRange:replaceRange];
[result replaceCharactersInRange:replaceRange withString:[NSString stringWithFormat:@"_%@", digits]];
digitsRange = [result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet] options:kNilOptions range:NSMakeRange(digitsRangeEnd.location+1, result.length-digitsRangeEnd.location-1)];
range = [result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet] options:0 range:NSMakeRange(end.location + 1, result.length - end.location - 1)];
}
return result;
};
return [[self alloc] initWithJSONToModelBlock:toModel
modelToJSONBlock:toJSON];
}];
}
+(instancetype)mapperFromUpperCaseToLowerCase
+ (instancetype)mapperForTitleCase
{
JSONModelKeyMapBlock toModel = ^ NSString* (NSString* keyName) {
NSString*lowercaseString = [keyName lowercaseString];
return lowercaseString;
};
JSONModelKeyMapBlock toJSON = ^ NSString* (NSString* keyName) {
NSString *uppercaseString = [keyName uppercaseString];
return uppercaseString;
};
return [[self alloc] initWithJSONToModelBlock:toModel
modelToJSONBlock:toJSON];
return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName)
{
return [keyName stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[keyName substringToIndex:1].uppercaseString];
}];
}
+ (instancetype)mapperFromUpperCaseToLowerCase
{
return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName)
{
return keyName.uppercaseString;
}];
}
+ (instancetype)mapper:(JSONKeyMapper *)baseKeyMapper withExceptions:(NSDictionary *)exceptions
{
NSArray *keys = exceptions.allKeys;
NSArray *values = [exceptions objectsForKeys:keys notFoundMarker:[NSNull null]];
NSDictionary *toModelMap = [NSDictionary dictionaryWithObjects:values forKeys:keys];
NSDictionary *toJsonMap = [NSDictionary dictionaryWithObjects:keys forKeys:values];
JSONModelKeyMapBlock toModel = ^NSString *(NSString *keyName) {
if (!keyName)
return nil;
if (toModelMap[keyName])
return toModelMap[keyName];
NSDictionary *toJSON = [JSONKeyMapper swapKeysAndValuesInDictionary:exceptions];
return baseKeyMapper.JSONToModelKeyBlock(keyName);
};
return [self baseMapper:baseKeyMapper withModelToJSONExceptions:toJSON];
}
JSONModelKeyMapBlock toJson = ^NSString *(NSString *keyName) {
+ (instancetype)baseMapper:(JSONKeyMapper *)baseKeyMapper withModelToJSONExceptions:(NSDictionary *)toJSON
{
return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName)
{
if (!keyName)
return nil;
if (toJsonMap[keyName])
return toJsonMap[keyName];
if (toJSON[keyName])
return toJSON[keyName];
return baseKeyMapper.modelToJSONKeyBlock(keyName);
};
return [[self alloc] initWithJSONToModelBlock:toModel modelToJSONBlock:toJson];
}];
}
@end
//
// JSONValueTransformer.h
// JSONModel
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import "JSONModelArray.h"
/////////////////////////////////////////////////////////////////////////////////////////////
......@@ -44,7 +32,7 @@ extern BOOL isNull(id value);
*/
@interface JSONValueTransformer : NSObject
@property (strong, nonatomic, readonly) NSDictionary* primitivesNames;
@property (strong, nonatomic, readonly) NSDictionary *primitivesNames;
/** @name Resolving cluster class names */
/**
......@@ -54,7 +42,7 @@ extern BOOL isNull(id value);
* @param sourceClass the class to get the umbrella class for
* @return Class
*/
+(Class)classByResolvingClusterClasses:(Class)sourceClass;
+ (Class)classByResolvingClusterClasses:(Class)sourceClass;
#pragma mark - NSMutableString <-> NSString
/** @name Transforming to Mutable copies */
......@@ -63,7 +51,7 @@ extern BOOL isNull(id value);
* @param string incoming string
* @return mutable string
*/
-(NSMutableString*)NSMutableStringFromNSString:(NSString*)string;
- (NSMutableString *)NSMutableStringFromNSString:(NSString *)string;
#pragma mark - NSMutableArray <-> NSArray
/**
......@@ -71,16 +59,7 @@ extern BOOL isNull(id value);
* @param array incoming array
* @return mutable array
*/
-(NSMutableArray*)NSMutableArrayFromNSArray:(NSArray*)array;
#pragma mark - NS(Mutable)Array <- JSONModelArray
/**
* Transforms an array to a JSONModelArray
* @param array incoming array
* @return JSONModelArray
*/
-(NSArray*)NSArrayFromJSONModelArray:(JSONModelArray*)array;
-(NSMutableArray*)NSMutableArrayFromJSONModelArray:(JSONModelArray*)array;
- (NSMutableArray *)NSMutableArrayFromNSArray:(NSArray *)array;
#pragma mark - NSMutableDictionary <-> NSDictionary
/**
......@@ -88,7 +67,7 @@ extern BOOL isNull(id value);
* @param dict incoming dictionary
* @return mutable dictionary
*/
-(NSMutableDictionary*)NSMutableDictionaryFromNSDictionary:(NSDictionary*)dict;
- (NSMutableDictionary *)NSMutableDictionaryFromNSDictionary:(NSDictionary *)dict;
#pragma mark - NSSet <-> NSArray
/** @name Transforming Sets */
......@@ -97,28 +76,28 @@ extern BOOL isNull(id value);
* @param array incoming array
* @return set with the array's elements
*/
-(NSSet*)NSSetFromNSArray:(NSArray*)array;
- (NSSet *)NSSetFromNSArray:(NSArray *)array;
/**
* Transforms an array to a mutable set
* @param array incoming array
* @return mutable set with the array's elements
*/
-(NSMutableSet*)NSMutableSetFromNSArray:(NSArray*)array;
- (NSMutableSet *)NSMutableSetFromNSArray:(NSArray *)array;
/**
* Transforms a set to an array
* @param set incoming set
* @return an array with the set's elements
*/
-(NSArray*)JSONObjectFromNSSet:(NSSet*)set;
- (NSArray *)JSONObjectFromNSSet:(NSSet *)set;
/**
* Transforms a mutable set to an array
* @param set incoming mutable set
* @return an array with the set's elements
*/
-(NSArray*)JSONObjectFromNSMutableSet:(NSMutableSet*)set;
- (NSArray *)JSONObjectFromNSMutableSet:(NSMutableSet *)set;
#pragma mark - BOOL <-> number/string
/** @name Transforming JSON types */
......@@ -127,21 +106,21 @@ extern BOOL isNull(id value);
* @param number the number to convert
* @return the resulting number
*/
-(NSNumber*)BOOLFromNSNumber:(NSNumber*)number;
- (NSNumber *)BOOLFromNSNumber:(NSNumber *)number;
/**
* Transforms a number object to a bool number object
* @param string the string value to convert, "0" converts to NO, everything else to YES
* @return the resulting number
*/
-(NSNumber*)BOOLFromNSString:(NSString*)string;
- (NSNumber *)BOOLFromNSString:(NSString *)string;
/**
* Transforms a BOOL value to a bool number object
* @param number an NSNumber value coming from the model
* @return the result number
*/
-(NSNumber*)JSONObjectFromBOOL:(NSNumber*)number;
- (NSNumber *)JSONObjectFromBOOL:(NSNumber *)number;
#pragma mark - string <-> number
/**
......@@ -149,28 +128,28 @@ extern BOOL isNull(id value);
* @param string the string to convert
* @return the resulting number
*/
-(NSNumber*)NSNumberFromNSString:(NSString*)string;
- (NSNumber *)NSNumberFromNSString:(NSString *)string;
/**
* Transforms a number object to a string object
* @param number the number to convert
* @return the resulting string
*/
-(NSString*)NSStringFromNSNumber:(NSNumber*)number;
- (NSString *)NSStringFromNSNumber:(NSNumber *)number;
/**
* Transforms a string object to a nsdecimalnumber object
* @param string the string to convert
* @return the resulting number
*/
-(NSDecimalNumber*)NSDecimalNumberFromNSString:(NSString*)string;
- (NSDecimalNumber *)NSDecimalNumberFromNSString:(NSString *)string;
/**
* Transforms a nsdecimalnumber object to a string object
* @param number the number to convert
* @return the resulting string
*/
-(NSString*)NSStringFromNSDecimalNumber:(NSDecimalNumber*)number;
- (NSString *)NSStringFromNSDecimalNumber:(NSDecimalNumber *)number;
#pragma mark - string <-> url
......@@ -180,14 +159,14 @@ extern BOOL isNull(id value);
* @param string the string to convert
* @return the resulting url object
*/
-(NSURL*)NSURLFromNSString:(NSString*)string;
- (NSURL *)NSURLFromNSString:(NSString *)string;
/**
* Transforms an NSURL object to a string
* @param url the url object to convert
* @return the resulting string
*/
-(NSString*)JSONObjectFromNSURL:(NSURL*)url;
- (NSString *)JSONObjectFromNSURL:(NSURL *)url;
#pragma mark - string <-> time zone
......@@ -197,7 +176,7 @@ extern BOOL isNull(id value);
* @param string the string to convert
* @return the resulting NSTimeZone object
*/
- (NSTimeZone *)NSTimeZoneFromNSString:(NSString*)string;
- (NSTimeZone *)NSTimeZoneFromNSString:(NSString *)string;
/**
* Transforms an NSTimeZone object to a string
......@@ -215,8 +194,8 @@ extern BOOL isNull(id value);
* them in a category, so they have to stay hidden here.
*/
//-(NSDate*)NSDateFromNSString:(NSString*)string;
//-(NSString*)JSONObjectFromNSDate:(NSDate*)date;
//- (NSDate *)NSDateFromNSString:(NSString *)string;
//- (NSString *)JSONObjectFromNSDate:(NSDate *)date;
#pragma mark - number <-> date
......@@ -225,6 +204,6 @@ extern BOOL isNull(id value);
* @param number the number to convert
* @return the resulting date
*/
- (NSDate*)NSDateFromNSNumber:(NSNumber*)number;
- (NSDate *)NSDateFromNSNumber:(NSNumber *)number;
@end
//
// JSONValueTransformer.m
//
// @version 1.2
// @author Marin Todorov (http://www.underplot.com) and contributors
//
// Copyright (c) 2012-2015 Marin Todorov, Underplot ltd.
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// JSONModel
//
#import "JSONValueTransformer.h"
#import "JSONModelArray.h"
#pragma mark - functions
extern BOOL isNull(id value)
......@@ -82,26 +70,9 @@ extern BOOL isNull(id value)
#pragma mark - NSMutableArray <-> NSArray
-(NSMutableArray*)NSMutableArrayFromNSArray:(NSArray*)array
{
if ([array isKindOfClass:[JSONModelArray class]]) {
//it's a jsonmodelarray already, just return it
return (id)array;
}
return [NSMutableArray arrayWithArray:array];
}
#pragma mark - NS(Mutable)Array <- JSONModelArray
-(NSArray*)NSArrayFromJSONModelArray:(JSONModelArray*)array
{
return (NSMutableArray*)array;
}
-(NSMutableArray*)NSMutableArrayFromJSONModelArray:(JSONModelArray*)array
{
return (NSMutableArray*)array;
}
#pragma mark - NSMutableDictionary <-> NSDictionary
-(NSMutableDictionary*)NSMutableDictionaryFromNSDictionary:(NSDictionary*)dict
{
......@@ -179,7 +150,7 @@ extern BOOL isNull(id value)
#pragma mark - string <-> number
-(NSNumber*)NSNumberFromNSString:(NSString*)string
{
return [NSNumber numberWithFloat: [string doubleValue]];
return [NSNumber numberWithDouble:[string doubleValue]];
}
-(NSString*)NSStringFromNSNumber:(NSNumber*)number
......@@ -201,7 +172,7 @@ extern BOOL isNull(id value)
-(NSURL*)NSURLFromNSString:(NSString*)string
{
// do not change this behavior - there are other ways of overriding it
// see: https://github.com/icanzilb/JSONModel/pull/119
// see: https://github.com/jsonmodel/jsonmodel/pull/119
return [NSURL URLWithString:string];
}
......@@ -258,7 +229,7 @@ extern BOOL isNull(id value)
}
#pragma mark - hidden transform for empty dictionaries
//https://github.com/icanzilb/JSONModel/issues/163
//https://github.com/jsonmodel/jsonmodel/issues/163
-(NSDictionary*)__NSDictionaryFromNSArray:(NSArray*)array
{
if (array.count==0) return @{};
......
Copyright (c) 2012-2016 Marin Todorov and JSONModel contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
JSONModel
Copyright (c) 2012-2014 Marin Todorov, Underplot ltd.
This code is distributed under the terms and conditions of the MIT license.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The MIT License in plain English: http://www.touch-code-magazine.com/JSONModel/MITLicense
## Magical Data Modelling Framework for JSON
# JSONModel - Magical Data Modeling Framework for JSON
### Version 1.2.0
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.
#####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.
See [CHANGELOG.md](CHANGELOG.md) for details on changes.
---
If you like JSONModel and use it, could you please:
## Installation
* star this repo
* send me some feedback. Thanks!
---
![JSONModel for iOS and OSX](http://jsonmodel.com/img/jsonmodel_logolike.png)
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.
[![](http://www.touch-code-magazine.com/img/json.png)](http://www.touch-code-magazine.com/img/json.png)
------------------------------------
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](https://github.com/icanzilb/JSONModel/archive/master.zip) 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:
### CocoaPods
```ruby
pod 'JSONModel'
```
If you want to read more about CocoaPods, have a look at [this short tutorial](http://www.raywenderlich.com/12139/introduction-to-cocoapods).
#### or 3) via Carthage
In your project's **Cartfile** add the JSONModel:
### Carthage
```ruby
github "icanzilb/JSONModel"
github "jsonmodel/jsonmodel"
```
#### Source code documentation
The source code includes class docs, which you can build yourself and import into Xcode:
### Manual
1. If you don't already have [appledoc](http://gentlebytes.com/appledoc/) installed, install it with [homebrew](http://brew.sh/) 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.
0. download the JSONModel repository
0. copy the JSONModel sub-folder into your Xcode project
0. link your app to SystemConfiguration.framework
------------------------------------
Basic usage
====================================
## Basic Usage
Consider you have a JSON like this:
```javascript
{"id":"10", "country":"Germany", "dialCode": 49, "isInEurope":true}
```
Consider you have JSON like this:
* Create a new Objective-C class for your data model and make it inherit the JSONModel class.
* Declare properties in your header file with the name of the JSON keys:
```json
{ "id": 10, "country": "Germany", "dialCode": 49, "isInEurope": true }
```
```objective-c
#import "JSONModel.h"
- 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 (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* country;
@property (strong, nonatomic) NSString* dialCode;
@property (assign, nonatomic) BOOL isInEurope;
@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 **.m** file.
* Initialize your model with data:
```objective-c
#import "CountryModel.h"
...
There's no need to do anything in the implementation (`.m`) file.
NSString* json = (fetch here JSON from Internet) ...
NSError* err = nil;
CountryModel* country = [[CountryModel alloc] initWithString:json error:&err];
- 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
* just copy country's value
* convert dialCode from number (in the JSON) to an NSString value
* finally convert isInEurope to a BOOL for your BOOL property
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](http://www.jsonmodel.com)
Class docs online: [http://jsonmodel.com/docs/](http://jsonmodel.com/docs/)
Step-by-step tutorials:
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:
* [How to fetch and parse JSON by using data models](http://www.touch-code-magazine.com/how-to-fetch-and-parse-json-by-using-data-models/)
- 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
* [Performance optimisation for working with JSON feeds via JSONModel](http://www.touch-code-magazine.com/performance-optimisation-for-working-with-json-feeds-via-jsonmodel/)
All you have to do is define the properties and their expected types.
* [How to make a YouTube app using MGBox and JSONModel](http://www.touch-code-magazine.com/how-to-make-a-youtube-app-using-mgbox-and-jsonmodel/)
## Examples
-------
Examples
=======
### Automatic name based mapping
#### Automatic name based mapping
<table>
<tr>
<td valign="top">
<pre>
```json
{
"id": "123",
"id": 123,
"name": "Product name",
"price": 12.95
}
</pre>
</td>
<td>
<pre>
```
```objc
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@end
```
@implementation ProductModel
@end
</pre>
</td>
</tr>
</table>
#### Model cascading (models including other models)
<table>
<tr>
<td valign="top">
<pre>
### Model cascading (models including other models)
```json
{
"order_id": 104,
"total_price": 13.45,
"product" : {
"id": "123",
"orderId": 104,
"totalPrice": 13.45,
"product": {
"id": 123,
"name": "Product name",
"price": 12.95
}
}
</pre>
</td>
<td valign="top">
<pre>
@interface OrderModel : JSONModel
@property (assign, nonatomic) int order_id;
@property (assign, nonatomic) float total_price;
@property (strong, nonatomic) <b>ProductModel*</b> product;
```
```objc
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@end
@implementation OrderModel
@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) float totalPrice;
@property (nonatomic) ProductModel *product;
@end
</pre>
</td>
</tr>
</table>
#### Model collections
<table>
<tr>
<td valign="top">
<pre>
```
### Model collections
```json
{
"order_id": 104,
"total_price": 103.45,
"products" : [
"orderId": 104,
"totalPrice": 103.45,
"products": [
{
"id": "123",
"id": 123,
"name": "Product #1",
"price": 12.95
},
{
"id": "137",
"id": 137,
"name": "Product #2",
"price": 82.95
}
]
}
</pre>
</td>
<td valign="top">
<pre>
<b>@protocol ProductModel
@end</b>
```
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@end
```objc
@protocol ProductModel;
@implementation ProductModel
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@end
@interface OrderModel : JSONModel
@property (assign, nonatomic) int order_id;
@property (assign, nonatomic) float total_price;
@property (strong, nonatomic) <b>NSArray&lt;ProductModel&gt;*</b> products;
@property (nonatomic) NSInteger orderId;
@property (nonatomic) float totalPrice;
@property (nonatomic) NSArray <ProductModel> *products;
@end
```
@implementation OrderModel
@end
</pre>
</td>
</tr>
</table>
#### Key mapping
<table>
<tr>
<td valign="top">
<pre>
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.
### Nested key mapping
```json
{
"order_id": 104,
"order_details" : [
"orderId": 104,
"orderDetails": [
{
"name": "Product#1",
"name": "Product #1",
"price": {
"usd": 12.95
}
}
]
}
</pre>
</td>
<td valign="top">
<pre>
```
```objc
@interface OrderModel : JSONModel
@property (assign, nonatomic) int id;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSString* productName;
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *productName;
@property (nonatomic) float price;
@end
@implementation OrderModel
+(JSONKeyMapper*)keyMapper
+ (JSONKeyMapper *)keyMapper
{
return [[JSONKeyMapper alloc] initWithDictionary:@{
<b> @"order_id": @"id",
@"order_details.name": @"productName",
@"order_details.price.usd": @"price"</b>
return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:@{
@"id": @"orderId",
@"productName": @"orderDetails.name",
@"price": @"orderDetails.price.usd"
}];
}
@end
</pre>
</td>
</tr>
</table>
#### Global key mapping (applies to all models in your app)
<table>
<tr>
<td valign="top">
<pre>
<b>[JSONModel setGlobalKeyMapper:[</b>
[JSONKeyMapper alloc] initWithDictionary:@{
@"item_id":@"ID",
@"item.name": @"itemName"
}]
<b>];</b>
</pre>
</td>
</tr>
</table>
#### Map automatically under_score case to camelCase
<table>
<tr>
<td valign="top">
<pre>
```
### Map automatically to snake_case
```json
{
"order_id": 104,
"order_product" : @"Product#1",
"order_price" : 12.95
"order_product": "Product #1",
"order_price": 12.95
}
</pre>
</td>
<td valign="top">
<pre>
@interface OrderModel : JSONModel
@property (assign, nonatomic) int orderId;
@property (assign, nonatomic) float orderPrice;
@property (strong, nonatomic) NSString* orderProduct;
```
```objc
@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) NSString *orderProduct;
@property (nonatomic) float orderPrice;
@end
@implementation OrderModel
+(JSONKeyMapper*)keyMapper
+ (JSONKeyMapper *)keyMapper
{
return <b>[JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];</b>
return [JSONKeyMapper mapperForSnakeCase];
}
@end
</pre>
</td>
</tr>
</table>
#### Optional properties (i.e. can be missing or null)
<table>
<tr>
<td valign="top">
<pre>
```
### Optional properties (i.e. can be missing or null)
```json
{
"id": "123",
"id": 123,
"name": null,
"price": 12.95
}
</pre>
</td>
<td>
<pre>
```
```objc
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString<b>&lt;Optional&gt;</b>* name;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSNumber<b>&lt;Optional&gt;</b>* uuid;
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString <Optional> *name;
@property (nonatomic) float price;
@property (nonatomic) NSNumber <Optional> *uuid;
@end
```
@implementation ProductModel
@end
</pre>
</td>
</tr>
</table>
#### Ignored properties (i.e. JSONModel completely ignores them)
<table>
<tr>
<td valign="top">
<pre>
### Ignored properties (i.e. JSONModel completely ignores them)
```json
{
"id": "123",
"id": 123,
"name": null
}
</pre>
</td>
<td>
<pre>
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString<b>&lt;Ignore&gt;</b>* customProperty;
@end
@implementation ProductModel
@end
</pre>
</td>
</tr>
</table>
```
#### Make all model properties optional (avoid if possible)
<table>
<tr>
<td valign="top">
<pre>
@implementation ProductModel
<b>+(BOOL)propertyIsOptional:(NSString*)propertyName
{
return YES;
}</b>
```objc
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString <Ignore> *customProperty;
@end
</pre>
</td>
</tr>
</table>
```
### Making scalar types optional
#### Lazy convert collection items from dictionaries to models
<table>
<tr>
<td valign="top">
<pre>
```json
{
"order_id": 104,
"total_price": 103.45,
"products" : [
{
"id": "123",
"name": "Product #1",
"price": 12.95
},
{
"id": "137",
"name": "Product #2",
"price": 82.95
}
]
"id": null
}
</pre>
</td>
<td valign="top">
<pre>
@protocol ProductModel
@end
```
```objc
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@property (nonatomic) NSInteger id;
@end
@implementation ProductModel
@end
@interface OrderModel : JSONModel
@property (assign, nonatomic) int order_id;
@property (assign, nonatomic) float total_price;
@property (strong, nonatomic) NSArray&lt;ProductModel, <b>ConvertOnDemand</b>&gt;* products;
@end
@implementation OrderModel
@end
</pre>
</td>
</tr>
</table>
#### Using the built-in thin HTTP client
```objective-c
//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) {
+ (BOOL)propertyIsOptional:(NSString *)propertyName
{
if ([propertyName isEqualToString:@"id"])
return YES;
//check err, process json ...
return NO;
}
}];
@end
```
#### Export model to NSDictionary or to JSON text
### Export model to `NSDictionary` or JSON
```objective-c
```objc
ProductModel *pm = [ProductModel new];
pm.name = @"Some Name";
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];
// convert to dictionary
NSDictionary *dict = [pm toDictionary];
// convert to json
NSString *string = [pm toJSONString];
```
#### Custom data transformers
### Custom data transformers
```objective-c
```objc
@interface JSONValueTransformer (CustomNSDate)
@end
@implementation JSONValueTransformer (CustomTransformer)
- (NSDate *)NSDateFromNSString:(NSString*)string {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:APIDateFormat];
- (NSDate *)NSDateFromNSString:(NSString *)string
{
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = APIDateFormat;
return [formatter dateFromString:string];
}
- (NSString *)JSONObjectFromNSDate:(NSDate *)date {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:APIDateFormat];
- (NSString *)JSONObjectFromNSDate:(NSDate *)date
{
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = APIDateFormat;
return [formatter stringFromDate:date];
}
@end
```
#### Custom handling for specific properties
```objective-c
### Custom getters/setters
```objc
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSLocale *locale;
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@property (nonatomic) NSLocale *locale;
@end
@implementation ProductModel
// Convert and assign the locale property
- (void)setLocaleWithNSString:(NSString*)string {
- (void)setLocaleWithNSString:(NSString *)string
{
self.locale = [NSLocale localeWithLocaleIdentifier:string];
}
- (NSString *)JSONObjectForLocale {
- (void)setLocaleWithNSDictionary:(NSDictionary *)dictionary
{
self.locale = [NSLocale localeWithLocaleIdentifier:dictionary[@"identifier"]];
}
- (NSString *)JSONObjectForLocale
{
return self.locale.localeIdentifier;
}
@end
```
* json validation
* error handling
* custom data validation
* automatic compare and equality features
* and more.
### Custom JSON validation
-------
```objc
Misc
=======
@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
Author: [Marin Todorov](http://www.touch-code-magazine.com)
@implementation ProductModel
Contributors: Christian Hoffmann, Mark Joslin, Julien Vignali, Symvaro GmbH, BB9z.
Also everyone who did successful [pull requests](https://github.com/icanzilb/JSONModel/graphs/contributors).
- (BOOL)validate:(NSError **)error
{
if (![super validate:error])
return NO;
Change log : [https://github.com/icanzilb/JSONModel/blob/master/Changelog.md](https://github.com/icanzilb/JSONModel/blob/master/Changelog.md)
if (self.name.length < self.minNameLength.integerValue)
{
*error = [NSError errorWithDomain:@"me.mycompany.com" code:1 userInfo:nil];
return NO;
}
return YES;
}
@end
```
-------
#### License
This code is distributed under the terms and conditions of the MIT license.
## License
-------
#### Contribution guidelines
MIT licensed - see [LICENSE](LICENSE) file.
**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.
## Contributing
We love pull requests! See [CONTRIBUTING.md](CONTRIBUTING.md) for full details.
......@@ -32,7 +32,7 @@ PODS:
- FMDB/standard (2.6.2)
- IQKeyboardManager (3.2.4)
- JPushSDK (1.8.2)
- JSONModel (1.2.0)
- JSONModel (1.7.0)
- Masonry (1.0.1)
- MBProgressHUD (0.9.2)
- MJRefresh (3.1.3)
......@@ -57,7 +57,7 @@ DEPENDENCIES:
- FMDB (~> 2.5)
- IQKeyboardManager (~> 3.2.3)
- JPushSDK (~> 1.8.2)
- JSONModel (~> 1.2.0)
- JSONModel (~> 1.7.0)
- Masonry (~> 1.0.1)
- MBProgressHUD (~> 0.9.1)
- MJRefresh (~> 3.1.0)
......@@ -76,7 +76,7 @@ SPEC CHECKSUMS:
FMDB: 854a0341b4726e53276f2a8996f06f1b80f9259a
IQKeyboardManager: 555b1231fefafb21b19278d7cca72986a27b748b
JPushSDK: c68dd04c595a5c93aa003f212974010790410d8e
JSONModel: 12523685c4b623553ccf844bbbf7007624317b2c
JSONModel: 840bc0fcffb24b8454d2c026bf26fea454b8e98d
Masonry: a1a931a0d08870ed8ae415a2ea5ea68ebcac77df
MBProgressHUD: 1569cf7ace17a8bac47aabfbb8580a49690386d1
MJRefresh: e9005c294dd8a3d08cc7c50eea2b5016673f29c4
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -132,29 +132,24 @@ LICENSE Copyright 2010 - 2014 JPush.cn, Inc. All rights reserved.
## JSONModel
JSONModel
Copyright (c) 2012-2014 Marin Todorov, Underplot ltd.
This code is distributed under the terms and conditions of the MIT license.
Copyright (c) 2012-2016 Marin Todorov and JSONModel contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The MIT License in plain English: http://www.touch-code-magazine.com/JSONModel/MITLicense
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## MBProgressHUD
......
......@@ -171,29 +171,24 @@ SOFTWARE.
</dict>
<dict>
<key>FooterText</key>
<string>JSONModel
Copyright (c) 2012-2014 Marin Todorov, Underplot ltd.
This code is distributed under the terms and conditions of the MIT license.
<string>Copyright (c) 2012-2016 Marin Todorov and JSONModel contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The MIT License in plain English: http://www.touch-code-magazine.com/JSONModel/MITLicense
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</string>
<key>Title</key>
<string>JSONModel</string>
......
......@@ -15,5 +15,5 @@ pod 'JPushSDK', '~> 1.8.2'
pod 'RETableViewManager', '~> 1.6'
pod 'YLProgressBar', '~> 3.8.1'
pod 'WYPopoverController', '~> 0.3.9'
pod 'JSONModel', '~> 1.2.0'
pod 'JSONModel', '~> 1.7.0'
pod 'DZNEmptyDataSet', '~> 1.8.1'
......@@ -3123,8 +3123,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_IDENTITY = "iPhone Distribution: Shanghai Gomore Information Technology Co.,Ltd";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Shanghai Gomore Information Technology Co.,Ltd";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
......@@ -3140,7 +3140,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.gomoe.total;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE = "f96494cb-c220-43ce-8034-75e000c2193f";
SWIFT_OBJC_BRIDGING_HEADER = "total/total-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = 1;
......@@ -3171,7 +3171,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.gomoe.total;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE = "f96494cb-c220-43ce-8034-75e000c2193f";
SWIFT_OBJC_BRIDGING_HEADER = "total/total-Bridging-Header.h";
TARGETED_DEVICE_FAMILY = 1;
USER_HEADER_SEARCH_PATHS = "$(PODS_ROOT)/**";
......
......@@ -326,8 +326,6 @@
stateStr = GTO_LICENCE__STATE_APPROVED;
}else if(indexPath.row == 7){
stateStr =GTO_LICENCE__STATE_FINISHED;
}else {
}
[self.delegate getBoltValueSelectRow:stateStr];
}
......
......@@ -993,25 +993,25 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *capacity;
@property (nonatomic, strong) NSNumber *capacity;
/**
* 质量,单位公斤
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quality;
@property (nonatomic, strong) NSNumber *quality;
/**
* 密度
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *density;
@property (nonatomic, strong) NSNumber *density;
/**
* 标准体积
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *volume;
@property (nonatomic, strong) NSNumber *volume;
@end /* interface GasMeasureValue */
......@@ -1530,7 +1530,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quantity;
@property (nonatomic, strong) NSNumber *quantity;
/**
* 明细状态
*
......@@ -1593,7 +1593,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *guidancePrice;
@property (nonatomic, strong) NSNumber *guidancePrice;
/**
* 售价
* <p>
......@@ -1626,7 +1626,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *salePrice;
@property (nonatomic, strong) NSNumber *salePrice;
/**
* 生效时间
*
......@@ -1740,13 +1740,13 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *qty;
@property (nonatomic, strong) NSNumber *qty;
/**
* 配油金额(元)
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *amount;
@property (nonatomic, strong) NSNumber *amount;
/**
* 配油单号
*
......@@ -1820,7 +1820,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *total;
@property (nonatomic, strong) NSNumber *total;
/**
* 付款凭证
*
......@@ -2288,7 +2288,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quantity;
@property (nonatomic, strong) NSNumber *quantity;
/**
* 油库
*
......@@ -2336,13 +2336,13 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *price;
@property (nonatomic, strong) NSNumber *price;
/**
* 金额
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *total;
@property (nonatomic, strong) NSNumber *total;
/**
* SO单是否已导出
*
......@@ -2462,13 +2462,13 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *billMeasure;
@property (nonatomic, strong) NSNumber *billMeasure;
/**
* 发油公斤数
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *realMeasure;
@property (nonatomic, strong) NSNumber *realMeasure;
/**
* 备注
*
......@@ -2504,19 +2504,19 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *pickFuelDensity;
@property (nonatomic, strong) NSNumber *pickFuelDensity;
/**
* 发油升数
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *pickFuelDensityCapacity;
@property (nonatomic, strong) NSNumber *pickFuelDensityCapacity;
/**
* 损耗升数
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *wasterCapacity;
@property (nonatomic, strong) NSNumber *wasterCapacity;
/**
* 收油营业日期
*
......@@ -2528,7 +2528,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *wasterRate;
@property (nonatomic, strong) NSNumber *wasterRate;
/**
* 承运商
*
......@@ -2540,7 +2540,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *price;
@property (nonatomic, strong) NSNumber *price;
@end /* interface ReceiveBill */
......@@ -2888,7 +2888,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quantity;
@property (nonatomic, strong) NSNumber *quantity;
/**
* 备注
*
......@@ -2912,7 +2912,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *price;
@property (nonatomic, strong) NSNumber *price;
/**
* 配送区域
*
......@@ -2966,7 +2966,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *price;
@property (nonatomic, strong) NSNumber *price;
/**
* (no documentation provided)
*
......@@ -3026,13 +3026,13 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *reqPrice;
@property (nonatomic, strong) NSNumber *reqPrice;
/**
* 申请数量
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quantity;
@property (nonatomic, strong) NSNumber *quantity;
/**
* 备注
*
......@@ -3068,7 +3068,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *minQuantity;
@property (nonatomic, strong) NSNumber *minQuantity;
@end /* interface ContractNumber */
......@@ -3125,7 +3125,7 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *total;
@property (nonatomic, strong) NSNumber *total;
@end /* interface DepotInv */
......@@ -3188,19 +3188,19 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *price;
@property (nonatomic, strong) NSNumber *price;
/**
* 建仓数量(吨)
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quantity;
@property (nonatomic, strong) NSNumber *quantity;
/**
* 建仓金额
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *amount;
@property (nonatomic, strong) NSNumber *amount;
/**
* 付款时间范围
*
......@@ -3230,25 +3230,25 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *unpayAmount;
@property (nonatomic, strong) NSNumber *unpayAmount;
/**
* 未增加库存数
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *undepotInv;
@property (nonatomic, strong) NSNumber *undepotInv;
/**
* 已缴纳保证金额
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *payMarginAmount;
@property (nonatomic, strong) NSNumber *payMarginAmount;
/**
* 剩余库存
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *total;
@property (nonatomic, strong) NSNumber *total;
@end /* interface DepotBill */
......@@ -3296,19 +3296,19 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *beforeTotal;
@property (nonatomic, strong) NSNumber *beforeTotal;
/**
* (no documentation provided)
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *subTotal;
@property (nonatomic, strong) NSNumber *subTotal;
/**
* (no documentation provided)
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *nowTotal;
@property (nonatomic, strong) NSNumber *nowTotal;
/**
* (no documentation provided)
*
......@@ -3398,13 +3398,13 @@ extern NSString * const POSITIONTYPE_NONE;
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *quantity;
@property (nonatomic, strong) NSNumber *quantity;
/**
* (no documentation provided)
*
*
*/
@property (nonatomic, strong) NSDecimalNumber *realQuantity;
@property (nonatomic, strong) NSNumber *realQuantity;
/**
* (no documentation provided)
*
......
......@@ -79,8 +79,8 @@
//#define HTTP_LOCAL_BASE_URL @"http://218.244.151.129:7580"
////正式环境
//#define HTTP_REST_API_BASE_URL @"http://139.196.39.77:7080/total-server/rest"
//#define HTTP_LOCAL_BASE_URL @"http://139.196.39.77:7080"
#define HTTP_REST_API_BASE_URL @"http://139.196.39.77:7080/total-server/rest"
#define HTTP_LOCAL_BASE_URL @"http://139.196.39.77:7080"
//
//测试环境
//#define HTTP_REST_API_BASE_URL @"http://139.196.39.77:8180/total-server/rest"
......@@ -96,8 +96,6 @@
#define HTTP_WEATHER_URL @"http://apis.baidu.com/heweather/weather/free"
//refreshUpdateDate
#define PurchaseNoticeUpdateDate @"purchaseNoticeUpdateDate"
#define TemplateNameUpdateDate @"templateNameUpdateDate"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment