JSONValueTransformer.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //
  2. // JSONValueTransformer.m
  3. // JSONModel
  4. //
  5. #import "JSONValueTransformer.h"
  6. #pragma mark - functions
  7. extern BOOL isNull(id value)
  8. {
  9. if (!value) return YES;
  10. if ([value isKindOfClass:[NSNull class]]) return YES;
  11. return NO;
  12. }
  13. @implementation JSONValueTransformer
  14. -(id)init
  15. {
  16. self = [super init];
  17. if (self) {
  18. _primitivesNames = @{@"f":@"float", @"i":@"int", @"d":@"double", @"l":@"long", @"c":@"BOOL", @"s":@"short", @"q":@"long",
  19. //and some famous aliases of primitive types
  20. // BOOL is now "B" on iOS __LP64 builds
  21. @"I":@"NSInteger", @"Q":@"NSUInteger", @"B":@"BOOL",
  22. @"@?":@"Block"};
  23. }
  24. return self;
  25. }
  26. +(Class)classByResolvingClusterClasses:(Class)sourceClass
  27. {
  28. //check for all variations of strings
  29. if ([sourceClass isSubclassOfClass:[NSString class]]) {
  30. return [NSString class];
  31. }
  32. //check for all variations of numbers
  33. if ([sourceClass isSubclassOfClass:[NSNumber class]]) {
  34. return [NSNumber class];
  35. }
  36. //check for all variations of dictionaries
  37. if ([sourceClass isSubclassOfClass:[NSArray class]]) {
  38. return [NSArray class];
  39. }
  40. //check for all variations of arrays
  41. if ([sourceClass isSubclassOfClass:[NSDictionary class]]) {
  42. return [NSDictionary class];
  43. }
  44. //check for all variations of dates
  45. if ([sourceClass isSubclassOfClass:[NSDate class]]) {
  46. return [NSDate class];
  47. }
  48. //no cluster parent class found
  49. return sourceClass;
  50. }
  51. #pragma mark - NSMutableString <-> NSString
  52. -(NSMutableString*)NSMutableStringFromNSString:(NSString*)string
  53. {
  54. return [NSMutableString stringWithString:string];
  55. }
  56. #pragma mark - NSMutableArray <-> NSArray
  57. -(NSMutableArray*)NSMutableArrayFromNSArray:(NSArray*)array
  58. {
  59. return [NSMutableArray arrayWithArray:array];
  60. }
  61. #pragma mark - NSMutableDictionary <-> NSDictionary
  62. -(NSMutableDictionary*)NSMutableDictionaryFromNSDictionary:(NSDictionary*)dict
  63. {
  64. return [NSMutableDictionary dictionaryWithDictionary:dict];
  65. }
  66. #pragma mark - NSSet <-> NSArray
  67. -(NSSet*)NSSetFromNSArray:(NSArray*)array
  68. {
  69. return [NSSet setWithArray:array];
  70. }
  71. -(NSMutableSet*)NSMutableSetFromNSArray:(NSArray*)array
  72. {
  73. return [NSMutableSet setWithArray:array];
  74. }
  75. -(id)JSONObjectFromNSSet:(NSSet*)set
  76. {
  77. return [set allObjects];
  78. }
  79. -(id)JSONObjectFromNSMutableSet:(NSMutableSet*)set
  80. {
  81. return [set allObjects];
  82. }
  83. //
  84. // 0 converts to NO, everything else converts to YES
  85. //
  86. #pragma mark - BOOL <-> number/string
  87. -(NSNumber*)BOOLFromNSNumber:(NSNumber*)number
  88. {
  89. if (isNull(number)) return [NSNumber numberWithBool:NO];
  90. return [NSNumber numberWithBool: number.intValue==0?NO:YES];
  91. }
  92. -(NSNumber*)BOOLFromNSString:(NSString*)string
  93. {
  94. if (string != nil &&
  95. ([string caseInsensitiveCompare:@"true"] == NSOrderedSame ||
  96. [string caseInsensitiveCompare:@"yes"] == NSOrderedSame)) {
  97. return [NSNumber numberWithBool:YES];
  98. }
  99. return [NSNumber numberWithBool: ([string intValue]==0)?NO:YES];
  100. }
  101. -(NSNumber*)JSONObjectFromBOOL:(NSNumber*)number
  102. {
  103. return [NSNumber numberWithBool: number.intValue==0?NO:YES];
  104. }
  105. #pragma mark - string/number <-> float
  106. -(float)floatFromObject:(id)obj
  107. {
  108. return [obj floatValue];
  109. }
  110. -(float)floatFromNSString:(NSString*)string
  111. {
  112. return [self floatFromObject:string];
  113. }
  114. -(float)floatFromNSNumber:(NSNumber*)number
  115. {
  116. return [self floatFromObject:number];
  117. }
  118. -(NSNumber*)NSNumberFromfloat:(float)f
  119. {
  120. return [NSNumber numberWithFloat:f];
  121. }
  122. #pragma mark - string <-> number
  123. -(NSNumber*)NSNumberFromNSString:(NSString*)string
  124. {
  125. return [NSNumber numberWithDouble:[string doubleValue]];
  126. }
  127. -(NSString*)NSStringFromNSNumber:(NSNumber*)number
  128. {
  129. return [number stringValue];
  130. }
  131. -(NSDecimalNumber*)NSDecimalNumberFromNSString:(NSString*)string
  132. {
  133. return [NSDecimalNumber decimalNumberWithString:string];
  134. }
  135. -(NSString*)NSStringFromNSDecimalNumber:(NSDecimalNumber*)number
  136. {
  137. return [number stringValue];
  138. }
  139. #pragma mark - string <-> url
  140. -(NSURL*)NSURLFromNSString:(NSString*)string
  141. {
  142. // do not change this behavior - there are other ways of overriding it
  143. // see: https://github.com/jsonmodel/jsonmodel/pull/119
  144. return [NSURL URLWithString:string];
  145. }
  146. -(NSString*)JSONObjectFromNSURL:(NSURL*)url
  147. {
  148. return [url absoluteString];
  149. }
  150. #pragma mark - string <-> date
  151. -(NSDateFormatter*)importDateFormatter
  152. {
  153. static dispatch_once_t onceInput;
  154. static NSDateFormatter* inputDateFormatter;
  155. dispatch_once(&onceInput, ^{
  156. inputDateFormatter = [[NSDateFormatter alloc] init];
  157. [inputDateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
  158. [inputDateFormatter setDateFormat:@"yyyy-MM-dd'T'HHmmssZZZ"];
  159. });
  160. return inputDateFormatter;
  161. }
  162. -(NSDate*)__NSDateFromNSString:(NSString*)string
  163. {
  164. string = [string stringByReplacingOccurrencesOfString:@":" withString:@""]; // this is such an ugly code, is this the only way?
  165. return [self.importDateFormatter dateFromString: string];
  166. }
  167. -(NSString*)__JSONObjectFromNSDate:(NSDate*)date
  168. {
  169. static dispatch_once_t onceOutput;
  170. static NSDateFormatter *outputDateFormatter;
  171. dispatch_once(&onceOutput, ^{
  172. outputDateFormatter = [[NSDateFormatter alloc] init];
  173. [outputDateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
  174. [outputDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZ"];
  175. });
  176. return [outputDateFormatter stringFromDate:date];
  177. }
  178. #pragma mark - number <-> date
  179. - (NSDate*)NSDateFromNSNumber:(NSNumber*)number
  180. {
  181. return [NSDate dateWithTimeIntervalSince1970:number.doubleValue];
  182. }
  183. #pragma mark - string <-> NSTimeZone
  184. - (NSTimeZone *)NSTimeZoneFromNSString:(NSString *)string {
  185. return [NSTimeZone timeZoneWithName:string];
  186. }
  187. - (id)JSONObjectFromNSTimeZone:(NSTimeZone *)timeZone {
  188. return [timeZone name];
  189. }
  190. #pragma mark - hidden transform for empty dictionaries
  191. //https://github.com/jsonmodel/jsonmodel/issues/163
  192. -(NSDictionary*)__NSDictionaryFromNSArray:(NSArray*)array
  193. {
  194. if (array.count==0) return @{};
  195. return (id)array;
  196. }
  197. -(NSMutableDictionary*)__NSMutableDictionaryFromNSArray:(NSArray*)array
  198. {
  199. if (array.count==0) return [[self __NSDictionaryFromNSArray:array] mutableCopy];
  200. return (id)array;
  201. }
  202. @end