公司的一个老项目中,总是因为json解析失败导致界面无法正常显示,导致客户工作无法正常展开。刚开始以为是各种转义符的原因,把转义符去掉之后偶尔还会出现,从后台数据库发现是特别奇怪的字符,根本没有见过😯,怎么办😰,输入法根本打不出来,没法像转义符那样替换掉,还有就算这个字符能够替换掉,要是出现其它的字符,还得重新搞。思考有没有一个办法一次性去掉所有的,有了,尝试着从UTF-8编码方向搞。
然后就是各种查,百度,根本没找到,那就查UTF-8编码表,找来找去将要放弃的时候终于在Wiki上找到了UTF-8编码表。突破点已经有了。
通过编码表中字符所对应的值来判断,取想要的字符,去掉不能解析的字符
上代码
NSString *json = @"{\"key\":\"!@#¥%……&*()——+~|、】【,。、?“:;‘?\"}";
NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
NSString *utf8Encode = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSMutableString *appendStr = [NSMutableString string];
for(int i =0; i < [utf8Encode length]; i++) {
//编码表字符所对应的10进制值
unsigned long character = (unsigned long)[utf8Encode characterAtIndex:i];
//字符
NSString *str = [utf8Encode substringWithRange:NSMakeRange(i, 1)];
//取范围内的值
if ((character > 0x0020u && character < 0x007Fu && character != 0x005Cu) ||
(character >= 0x2000u && character < 0xA000u) ||
(character >= 0xF900u && character < 0x10000u)) {
[appendStr appendString:str];
} else {
//打印不在范围内的字符和值
NSLog(@"error str:%@,%lu",str,character);
}
}
那思路是取能被正确解析的字符添加到新创建的appendStr
中。这里代码是尽可能缩小了范围。character > 0x0020u && character < 0x007Fu && character != 0x005Cu
排除了各种转义符,character >= 0x2000u && character < 0xA000u
是CJK的范围,character >= 0xF900u && character < 0x10000u
中包含中文标点符号。具体请看UTF-8编码表。
下面的代码尽可能的扩大了范围
/*
这里是其他的文字,可以测试
Latin:Iūnō IPA:ɐɷɸ accents: ᪱◌᷁◌︤ Greek:Πͷἧᾘ Cyril:йЖӜ
Armeni:վտրցւփ Hebrew: ֦ Arabic: ڤ ڴ ڕ Syriac:ܧܔ܊
Thaana:ޓޔޕ N'Ko:ߘ߆߷ Kana:さサぬヌ Hangul:ㅂㅒㅢ
*/
if ((character > 0x0020u && character < 0x007Fu && character != 0x005Cu) ||
(character >= 0x0120u && character < 0x0800u) ||
(character >= 0x1000u && character < 0xD000u) ||
(character >= 0xE000u && character < 0x10000u) ||
(character >= 0x40000u && character < 0x100000u)) {
[appendStr appendString:str];
} else {
DPLog(@"error str:%@,%lu",str,character);
}
现在已经得到了自己想要的字符串,但是还有一个问题,json中{"key":"value"} 的value内容可能会包含双引号
"
,这会导致解析失败。
很简单,通过判断"
前后是不是{[:]},
来区分json格式和value内容中的"
(因为前面我们已经把空格、换行符等去掉了,不会把json格式的"
去掉)
代码来了
//去除双引号"
NSMutableString *validJson = [NSMutableString stringWithString:appendStr];
NSMutableArray *rangeArr = [NSMutableArray arrayWithCapacity:0];
for (int i = 0; i < validJson.length - 1; i ++) {
NSRange range = NSMakeRange(i, 1);
NSString *character = [validJson substringWithRange:range];
if ([character isEqualToString:@"\""]) {
NSString *preCharacter = [validJson substringWithRange:NSMakeRange(i-1, 1)];
NSString *subCharacter = [validJson substringWithRange:NSMakeRange(i+1, 1)];
NSString *condition = @"{[:]},";
BOOL pre = [condition rangeOfString:preCharacter].location == NSNotFound;
BOOL sub = [condition rangeOfString:subCharacter].location == NSNotFound;
if (pre && sub) {
//说明是单" 消灭它
NSValue *value = [NSValue valueWithRange:range];
[rangeArr addObject:value];
}
}
}
//rangeArr reverse
rangeArr = (NSMutableArray *)[[rangeArr reverseObjectEnumerator] allObjects];
//消灭它
for (NSValue *value in rangeArr) {
NSRange range = [value rangeValue];
[validJson deleteCharactersInRange:range];
}
好了,到这里就已经完了,json中不能正常解析的字符就被我们清除了!✌️
下面是通过值打印字符的小东西,不过有点问题,能够勉强帮助我们一下。有谁知道解决办法的请留言
NSUInteger length = 0xFFFF - 0xF000;
unichar uni[length];
for(unichar i = 0xF000; i < 0xFFFF; i++) {
uni[i - 0xF000] = i;
}
NSString *testChar = [[NSString alloc] initWithCharacters:uni length:length];
NSLog(@"testChar: %@",testChar);