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