Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I wrote a JSON-parser by myself. You can use it if you want to by copying the code into your class source.</p> <p>You use it in this way:</p> <pre><code>NSObject *obj = [self jsonToObj:yourJsonString]; </code></pre> <p>It returns a <code>NSDictionary</code>, <code>NSString</code> or <code>NSArray</code> depending on the input. The difference between my parser and others is, that it also accepts numerical keys, which are not allowed in the JSON-standard. I can't guarantee that there are no bugs in it or that it works with all JSON-strings. Please give me some feedback, if it works for you!</p> <pre><code>-(NSObject*)jsonToObj:(NSString *)json { int nextOffset; return [self jsonToObj:json offset:0 nextOffset:&amp;nextOffset]; } static int indexOfChar(NSString *str, unichar c, int offset) { int length = [str length]; for (int i = offset; i &lt; length; i++) { if ([str characterAtIndex:i] == c) { return i; } } return -1; } static int indexOfNonWhitespace(NSString *str, int offset) { int len = [str length]; NSCharacterSet *cSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; for (int i = offset; i &lt; len; i++) { if (![cSet characterIsMember:[str characterAtIndex:i]]) { return i; } } return -1; } static int indexOfNonNumber(NSString *str, int offset) { int len = [str length]; for (int i = offset; i &lt; len; i++) { unichar c = [str characterAtIndex:i]; if (c != '-' &amp;&amp; c != '.' &amp;&amp; (c &lt; '0' || c &gt; '9')) return i; } return -1; } static int parseHex(NSString *hexStr) { unsigned int result = 0; int len = [hexStr length]; for (int i = 0; i &lt; len; i++) { result &lt;&lt;= 4; unsigned int v = 0; unichar c = [hexStr characterAtIndex:i]; if (c &gt;= '0' &amp;&amp; c &lt;= '9') { v = c-'0'; } else if (c &gt;= 'a' &amp;&amp; c &lt;= 'f') { v = c-'a'+10; } else if (c &gt;= 'A' &amp;&amp; c &lt;= 'F') { v = c-'A'+10; } result += v; } return result; } -(NSObject*)jsonToObj:(NSString *)json offset:(int)offset nextOffset:(int*)nextOffset { offset = indexOfNonWhitespace(json, offset); static NSString *jsonExceptionName = @"InvalidJSONException"; if (offset == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"no non-whitespace 1" userInfo:nil]; } unichar startChar = [json characterAtIndex:offset]; if (startChar == '{') { NSMutableDictionary *result = [NSMutableDictionary dictionary]; int curPos = offset+1; while (YES) { curPos = indexOfNonWhitespace(json, curPos); if (curPos == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"no non-whitespace 2" userInfo:nil]; } unichar curChar = [json characterAtIndex:curPos]; if (curChar == ',') { curPos++; continue; } else if (curChar == '}') { *nextOffset = curPos+1; return result; } unichar quotChar = curChar; if ((quotChar != '\'' &amp;&amp; quotChar != '"') || [json characterAtIndex:curPos-1]=='\\') { quotChar = 0; } NSString *key = nil; int semiIndex = 0; if (quotChar != 0) { int quotStart = curPos+1; int quotEnd = quotStart; while (YES) { quotEnd = indexOfChar(json, quotChar, quotEnd); if (quotEnd == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"quotation-end not found 1" userInfo:nil]; } if ([json characterAtIndex:quotEnd-1] != '\\') break; else quotEnd++; } key = [json substringWithRange:NSMakeRange(quotStart, quotEnd-quotStart)]; semiIndex = indexOfChar(json, ':', quotEnd); if (semiIndex == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"semicolon not found 1" userInfo:nil]; } } else { semiIndex = indexOfChar(json, ':', curPos); if (semiIndex == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"semicolon not found 2" userInfo:nil]; } key = [[json substringWithRange:NSMakeRange(curPos, semiIndex-curPos)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; } [result setObject:[self jsonToObj:json offset:semiIndex+1 nextOffset:&amp;curPos] forKey:key]; } } else if (startChar == '[') { NSMutableArray *result = [NSMutableArray array]; int curPos = offset+1; while (YES) { curPos = indexOfNonWhitespace(json, curPos); if (curPos == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"no non-whitespace 3" userInfo:nil]; } unichar curChar = [json characterAtIndex:curPos]; if (curChar == ',') { curPos++; continue; } else if (curChar == ']') { *nextOffset = curPos+1; return result; } [result addObject:[self jsonToObj:json offset:curPos nextOffset:&amp;curPos]]; } } else { unichar quotChar = startChar; if ((quotChar != '\'' &amp;&amp; quotChar != '"') || [json characterAtIndex:offset-1]=='\\') { quotChar = 0; } if (quotChar != 0) { int quotStart = offset+1; int quotEnd = quotStart; while (YES) { quotEnd = indexOfChar(json, quotChar, quotEnd); if (quotEnd == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"quotation-end not found 2" userInfo:nil]; } if ([json characterAtIndex:quotEnd-1] != '\\') break; else quotEnd++; } *nextOffset = quotEnd+1; NSString *str = [json substringWithRange:NSMakeRange(quotStart, quotEnd-quotStart)]; str = [str stringByReplacingOccurrencesOfString:@"\\\"" withString:@"\""]; NSMutableString *result = [NSMutableString stringWithCapacity:[str length]]; int len = [str length]; for (int i = 0; i &lt; len; i++) { unichar c = [str characterAtIndex:i]; if (c != '\\') { [result appendString:[NSString stringWithCharacters:&amp;c length:1]]; } else if (i+1 &lt; len) { unichar c2 = [str characterAtIndex:i+1]; if (c2 == '\\') { [result appendString:[NSString stringWithCharacters:&amp;c2 length:1]]; i++; } else if (c2 == 'u') { unichar cUni = parseHex([str substringWithRange:NSMakeRange(i+2, 4)]); [result appendString:[NSString stringWithCharacters:&amp;cUni length:1]]; i += 5; } } } return result; } else { int numberEnd = indexOfNonNumber(json, offset); if (numberEnd == -1) { @throw [NSException exceptionWithName:jsonExceptionName reason:@"number-end not found" userInfo:nil]; } //BOOL isFloat = indexOfChar(json, '.', offset)!=-1; NSString *numberStr = [json substringWithRange:NSMakeRange(offset, numberEnd-offset)]; *nextOffset = numberEnd; return numberStr; } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload