Last active
December 18, 2015 02:59
-
-
Save kristopherjohnson/5715018 to your computer and use it in GitHub Desktop.
Unescape a JSON string.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <SenTestingKit/SenTestingKit.h> | |
#import "NSString+KDJ_stringWthJSONString.h" | |
@interface KDJ_stringWthJSONString_Tests : SenTestCase | |
@end | |
@implementation KDJ_stringWthJSONString_Tests | |
- (void)test_stringFromJSONString { | |
STAssertEqualObjects(@"", [NSString stringWithJSONString:@"\"\""], @"empty string"); | |
STAssertEqualObjects(@"foo", [NSString stringWithJSONString:@"\"foo\""], @"simple string with no escaped characters"); | |
STAssertEqualObjects(@"\"", [NSString stringWithJSONString:@"\"\\\"\""], @"escaped double-quote character"); | |
STAssertEqualObjects(@"\\", [NSString stringWithJSONString:@"\"\\\\\""], @"escaped backslash"); | |
STAssertEqualObjects(@"/", [NSString stringWithJSONString:@"\"\\/\""], @"escaped forward slash"); | |
STAssertEqualObjects(@"\b", [NSString stringWithJSONString:@"\"\\b\""], @"escaped backspace"); | |
STAssertEqualObjects(@"\f", [NSString stringWithJSONString:@"\"\\f\""], @"escaped form feed"); | |
STAssertEqualObjects(@"\n", [NSString stringWithJSONString:@"\"\\n\""], @"escaped line feed"); | |
STAssertEqualObjects(@"\r", [NSString stringWithJSONString:@"\"\\r\""], @"escaped carriage return"); | |
STAssertEqualObjects(@"\t", [NSString stringWithJSONString:@"\"\\t\""], @"escaped tab"); | |
STAssertEqualObjects(@" ", [NSString stringWithJSONString:@"\"\\u0020\""], @"escaped Unicode"); | |
STAssertEqualObjects(@"zFoo", [NSString stringWithJSONString:@"\"\\u007aFoo\""], @"string with escaped Unicode"); | |
STAssertEqualObjects(@"She said, \"Hello!\"\n\tThen she said \"Goodbye.\"", | |
[NSString stringWithJSONString:@"\"She said, \\\"Hello!\\\"\\n\\tThen she said \\\"Goodbye.\\\"\""], | |
@"Complicated string"); | |
STAssertNil([NSString stringWithJSONString:@""], @"must start and end with double-quote characters"); | |
STAssertNil([NSString stringWithJSONString:@"foo"], @"must start and end with double-quote characters"); | |
STAssertNil([NSString stringWithJSONString:@"\"foo"], @"must start and end with double-quote characters"); | |
STAssertNil([NSString stringWithJSONString:@"foo\""], @"must start and end with double-quote characters"); | |
STAssertNil([NSString stringWithJSONString:@"\"foo\\\""], @"cannot end with backslash"); | |
STAssertNil([NSString stringWithJSONString:@"\"\\u123"], @"four characters must follow \\u"); | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface NSString (KDJ_stringWithJSONString) | |
// Return string from a JSON-encoded string, or return nil if argument is not a valid JSON string value. | |
// | |
// See RFC 4627 section 2.5 for details of JSON string representation. | |
// The string must begin and end with double-quote (") characters. | |
+ (NSString *)stringWithJSONString:(NSString *)jsonString; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSString+KDJ_stringWithJSONString.h" | |
@implementation NSString (KDJ_stringWithJSONString) | |
+ (NSString *)stringWithJSONString:(NSString *)jsonString { | |
NSUInteger len = [jsonString length]; | |
if (len < 2 || [jsonString characterAtIndex:0] != '"' || [jsonString characterAtIndex:(len - 1)] != '"') { | |
NSLog(@"%s: string does not begin and end with \" characters", __PRETTY_FUNCTION__); | |
return nil; | |
} | |
NSMutableString *result = [[NSMutableString alloc] initWithCapacity:(len-2)]; | |
NSUInteger limit = len - 1; | |
for (NSUInteger i = 1; i < limit; ++i) { | |
unichar character = [jsonString characterAtIndex:i]; | |
if (character == '\\') { | |
// Escape sequence | |
if (i == limit - 1) { | |
NSLog(@"%s: JSON string cannot end with single backslash", __PRETTY_FUNCTION__); | |
return nil; | |
} | |
++i; | |
unichar nextCharacter = [jsonString characterAtIndex:i]; | |
switch (nextCharacter) { | |
case 'b': | |
[result appendString:@"\b"]; | |
break; | |
case 'f': | |
[result appendString:@"\f"]; | |
break; | |
case 'n': | |
[result appendString:@"\n"]; | |
break; | |
case 'r': | |
[result appendString:@"\r"]; | |
break; | |
case 't': | |
[result appendString:@"\t"]; | |
break; | |
case 'u': | |
if ((i + 4) >= limit) { | |
NSLog(@"%s: insufficient characters remaining after \\u in JSON string", __PRETTY_FUNCTION__); | |
return nil; | |
} | |
{ | |
NSString *hexdigits = [jsonString substringWithRange:NSMakeRange(i + 1, 4)]; | |
i += 4; | |
NSScanner *scanner = [NSScanner scannerWithString:hexdigits]; | |
unsigned int hexValue = 0; | |
if (![scanner scanHexInt:&hexValue]) { | |
NSLog(@"%s: invalid hex digits following \\u", __PRETTY_FUNCTION__); | |
} | |
[result appendFormat:@"%C", (unichar)hexValue]; | |
} | |
break; | |
default: | |
[result appendFormat:@"%C", nextCharacter]; | |
break; | |
} | |
} | |
else { | |
// No escape | |
[result appendFormat:@"%C", character]; | |
} | |
} | |
// Return an immutable copy | |
return [NSString stringWithString:result]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It turns out that this code is unnecessary. See http://stackoverflow.com/questions/16948427/how-can-you-deserialize-an-escaped-json-string-with-nsjsonserialization