├── README.md ├── LICENSE ├── OCFURLQuery.h └── OCFURLQuery.m /README.md: -------------------------------------------------------------------------------- 1 | URLQueryToCocoa 2 | =============== 3 | 4 | Parses a Ruby-ish URL query string into Cocoa classes like `NSJSONSerializer`. 5 | 6 | For example having the URL query string 7 | 8 | users[0][firstName]=Amin&users[0][lastName]=Negm&name=Devs&users[1][lastName]=Kienle&users[1][firstName]=Christian 9 | 10 | you will get 11 | 12 | @{ 13 | name : @"Devs", 14 | users : 15 | @[ 16 | @{ 17 | firstName = @"Amin", 18 | lastName = @"Negm" 19 | }, 20 | @{ 21 | firstName = @"Christian", 22 | lastName = @"Kienle" 23 | } 24 | ] 25 | } 26 | 27 | You can set the key path pre- and postfixes ([]) and the delimiter between two assignments yo use the class for parsing both a GET query string and a POST form body. 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 anegmawad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /OCFURLQuery.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file will become a part of the OCFWebServer, which is a part of Objective-Cloud. 3 | 4 | Copyright (c) 2014, Amin Negm-Awad / amin@objective-cloud.com 5 | All rights reserved. 6 | 7 | */ 8 | 9 | #import 10 | 11 | @interface NSDictionary (OCFURLQuery) 12 | + (void)setDefaultURLQueryKeyPrefix:(NSString*)delimiter; 13 | + (NSString*)defaultURLQueryKeyPrefix; 14 | + (void)setDefaultURLQueryKeyPostfix:(NSString*)delimiter; 15 | + (NSString*)defaultURLQueryKeyPostfix; 16 | + (void)setDefaultURLQueryPairsDelimiter:(NSString*)delimiter; 17 | + (NSString*)defaultURLQueryPairsDelimiter; 18 | 19 | + (NSDictionary*)objectsFromURLQueryString:(NSString*)query; 20 | + (NSDictionary*)objectsFromURLQueryString:(NSString*)query withPairsDelimiter:(NSString*)delimiter keyPrefix:(NSString*)keyPrefix keyPostFix:(NSString*)keyPostfix; 21 | @end 22 | 23 | @interface NSMutableDictionary (OCFURLQuery) 24 | - (void)setObject:(NSString*)value forURLQueryKeyPath:(NSString*)keyPath; 25 | - (void)setObject:(NSString*)value forURLQueryKeyPath:(NSString*)keyPath keyPrefix:(NSString*)keyPrefix keyPostfix:(NSString*)keyPostfix; 26 | @end 27 | -------------------------------------------------------------------------------- /OCFURLQuery.m: -------------------------------------------------------------------------------- 1 | /* 2 | This file will become a part of OCFWebServer, which is a part of Objective-Cloud. 3 | 4 | Copyright (c) 2014, Amin Negm-Awad / amin@objective-cloud.com 5 | All rights reserved. 6 | 7 | */ 8 | 9 | #import "OCFURLQuery.h" 10 | 11 | 12 | @interface NSString (QueryToObject) 13 | - (BOOL)IsURLQueryIndex; 14 | @end 15 | 16 | @implementation NSString (QueryToObject) 17 | - (BOOL)IsURLQueryIndex 18 | { 19 | unichar firstLetter = [self characterAtIndex:0]; 20 | return (firstLetter>='0') && (firstLetter<='9'); 21 | } 22 | @end 23 | 24 | @interface NSMutableArray (OCFQueryKVC) 25 | - (void)setObject:(id)object forURLQueryKey:(NSString*)key; 26 | - (id)objectForURLQueryKey:(NSString*)key; 27 | @end 28 | 29 | @implementation NSMutableArray (OCFQueryKVC) 30 | - (void)setObject:(id)object forURLQueryKey:(NSString*)key 31 | { 32 | NSUInteger index = [key integerValue]; 33 | NSUInteger fillUpIndex = [self count]; 34 | 35 | while (fillUpIndex++<=index) 36 | { 37 | [self addObject:[NSNull null]]; 38 | } 39 | self[index] = object; 40 | } 41 | 42 | - (id)objectForURLQueryKey:(NSString*)key 43 | { 44 | NSUInteger index = [key integerValue]; 45 | id object = [NSNull null]; 46 | if ([self count]<=index) 47 | { 48 | [self setObject:object forURLQueryKey:key]; 49 | } 50 | else 51 | { 52 | object = self[index]; 53 | } 54 | return object; 55 | } 56 | @end 57 | 58 | @interface NSMutableDictionary (OCFURLQueryKVC) 59 | - (void)setObject:(id)object forURLQueryKey:(NSString*)key; 60 | - (id)objectForURLQueryKey:(NSString*)key; 61 | @end 62 | 63 | @implementation NSMutableDictionary (OCFURLQueryKVC) 64 | - (void)setObject:(id)object forURLQueryKey:(NSString*)key 65 | { 66 | self[key]=object; 67 | } 68 | 69 | - (id)objectForURLQueryKey:(NSString*)key 70 | { 71 | id object = self[key]; 72 | if (object==nil) 73 | { 74 | object = [NSNull null]; 75 | self[key]=object; 76 | } 77 | return object; 78 | } 79 | @end 80 | 81 | @implementation NSMutableDictionary (OCFURLQuery) 82 | 83 | - (void)setObject:(NSString*)value forURLQueryKeyPath:(NSString*)keyPath keyPrefix:(NSString*)keyPrefix keyPostfix:(NSString*)keyPostfix 84 | { 85 | value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 86 | 87 | keyPath = [keyPath stringByReplacingOccurrencesOfString:keyPostfix withString:@""]; 88 | NSArray *keys = [keyPath componentsSeparatedByString:keyPrefix]; 89 | 90 | NSAssert([keys count]>0, @"no components at all!?!?!?!"); 91 | 92 | NSUInteger keyIndex = 0; 93 | id omi = nil; 94 | id parent = nil; 95 | id node = self; 96 | 97 | NSString *key; 98 | NSString *parentKey; 99 | while (keyIndex<([keys count]-1)) 100 | { 101 | parentKey = key; 102 | key = keys[keyIndex++]; 103 | key = [key stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 104 | 105 | omi = parent; 106 | parent = node; 107 | 108 | Class collectionClass; 109 | if ([key IsURLQueryIndex]) 110 | { 111 | collectionClass = [NSMutableArray class]; 112 | } 113 | else 114 | { 115 | collectionClass = [NSMutableDictionary class]; 116 | } 117 | 118 | if ([parent isKindOfClass:[NSNull class]]) 119 | { 120 | parent = [collectionClass new]; 121 | [omi setObject:parent forURLQueryKey:parentKey]; 122 | } 123 | 124 | else if (![parent isKindOfClass:collectionClass]) 125 | { 126 | return; 127 | } 128 | node = [parent objectForURLQueryKey:key]; 129 | } 130 | parentKey = key; 131 | key = keys[keyIndex]; 132 | if ([key IsURLQueryIndex]) 133 | { 134 | if ([node isKindOfClass:[NSNull class]]) { 135 | node =[NSMutableArray new]; 136 | [parent setObject:node forURLQueryKey:parentKey]; 137 | } 138 | } 139 | else 140 | { 141 | if ([node isKindOfClass:[NSNull class]]) 142 | { 143 | node = [NSMutableDictionary new]; 144 | [parent setObject:node forURLQueryKey:parentKey]; 145 | } 146 | } 147 | [node setObject:value forURLQueryKey:key]; 148 | } 149 | 150 | - (void)setObject:(NSString*)value forURLQueryKeyPath:(NSString*)keyPath 151 | { 152 | [self setObject:value forURLQueryKeyPath:keyPath keyPrefix:[[self class] defaultURLQueryKeyPrefix] keyPostfix:[[self class] defaultURLQueryKeyPostfix]]; 153 | } 154 | @end 155 | 156 | @implementation NSDictionary (OCFURLQuery) 157 | 158 | static NSString *_keyPrefix = @"["; 159 | 160 | + (void)setDefaultURLQueryKeyPrefix:(NSString*)delimiter 161 | { 162 | _keyPrefix = delimiter; 163 | } 164 | 165 | + (NSString*)defaultURLQueryKeyPrefix 166 | { 167 | return _keyPrefix; 168 | } 169 | 170 | static NSString *_keyPostfix = @"]"; 171 | 172 | + (void)setDefaultURLQueryKeyPostfix:(NSString*)delimiter 173 | { 174 | _keyPostfix = delimiter; 175 | } 176 | 177 | + (NSString*)defaultURLQueryKeyPostfix 178 | { 179 | return _keyPostfix; 180 | } 181 | 182 | static NSString *_delimiter = @"&"; 183 | 184 | + (NSString*)defaultURLQueryPairsDelimiter 185 | { 186 | return _delimiter; 187 | } 188 | 189 | + (void)setDefaultURLQueryPairsDelimiter:(NSString*)delimiter 190 | { 191 | _delimiter = delimiter; 192 | } 193 | 194 | + (NSDictionary*)objectsFromURLQueryString:(NSString*)query 195 | { 196 | return [self objectsFromURLQueryString:query withPairsDelimiter:[self defaultURLQueryPairsDelimiter] keyPrefix:[self defaultURLQueryKeyPrefix] keyPostFix:[self defaultURLQueryKeyPostfix]]; 197 | } 198 | 199 | + (NSDictionary*)objectsFromURLQueryString:(NSString*)query withPairsDelimiter:(NSString*)delimiter keyPrefix:(NSString*)keyPrefix keyPostFix:(NSString*)keyPostfix 200 | { 201 | NSArray *assignments = [query componentsSeparatedByString:delimiter]; 202 | 203 | NSMutableDictionary *keyValuePairs = [NSMutableDictionary new]; 204 | for (NSString *assignment in assignments) 205 | { 206 | NSUInteger equalsSignLocation = [assignment rangeOfString:@"="].location; 207 | if (equalsSignLocation==NSNotFound) 208 | { 209 | return nil; 210 | } 211 | 212 | NSString *keyPath = [assignment substringToIndex:equalsSignLocation]; 213 | NSString *value = [assignment substringFromIndex:equalsSignLocation+1]; 214 | value = [value stringByRemovingPercentEncoding]; 215 | if (value==nil) { 216 | value = @""; 217 | } 218 | 219 | 220 | [keyValuePairs setObject:value forURLQueryKeyPath:keyPath keyPrefix:keyPrefix keyPostfix:keyPostfix]; 221 | 222 | } 223 | return keyValuePairs; 224 | } 225 | 226 | @end 227 | --------------------------------------------------------------------------------