如何使用NSJSONSerialization反序列化转义的JSON字符串?
我有一个iOS应用程序需要处理来自Web服务的响应。 响应是包含序列化JSON对象的序列化JSON字符串,如下所示:
"{ \"name\" : \"Bob\", \"age\" : 21 }"
请注意,此响应是JSON 字符串 ,而不是JSON对象。 我需要做的是反序列化字符串,以便我得到这个:
{ "name" : "Bob", "age" : 21 }
然后我可以使用+[NSJSONSerialization JSONObjectWithData:options:error:]
将其反序列化为NSDictionary
。
但是,我该如何做到第一步呢? 也就是说,我如何“unescape”字符串,以便我有一个序列化的JSON对象? +[NSJSONSerialization JSONObjectWithData:options:error:]
仅在顶级对象是数组或字典时有效; 它不适用于字符串。
我最终编写了自己的JSON字符串解析器 ,我希望它符合RFC 4627的2.5节 。 但我怀疑我使用NSJSONSerialization
或其他一些可用的方法忽略了一些简单的方法。
如果你有嵌套的JSON,那么只需调用两次JSONObjectWithData
:
NSString *string = @"\"{ \\\"name\\\" : \\\"Bob\\\", \\\"age\\\" : 21 }\""; // --> the string // "{ \"name\" : \"Bob\", \"age\" : 21 }" NSError *error; NSString *outerJson = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error]; // --> the string // { "name" : "Bob", "age" : 21 } NSDictionary *innerJson = [NSJSONSerialization JSONObjectWithData:[outerJson dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error]; // --> the dictionary // { age = 21; name = Bob; }
将字符串转换为数据:
NSString *string = @"{ \"name\" : \"Bob\", \"age\" : 21 }"; NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
只需切断前导和尾随引号,然后将所有\“s替换为”:
NSString *sub = [original substringWithRange:(NSRange){ 1, original.length - 2 }]; NSString *unescaped = [sub stringByReplacingOccurrencesOfString:@"\\\" withString:@"\"];
首先应该问一下,为什么服务器只是不包含JSON,作为子结构。
但不管怎么说。 你得到的字符串似乎是一个转义的 JSON。 实际上意味着什么,完全取决于Web服务开发人员。 我怀疑,只有双引号和逃脱本身已经逃脱了\
。 结果字符串不是“序列化” – JSON已经序列化 – 但已编码 。 为了还原它 – 你需要“unescape”或再次解码它:
一个小的C ++片段显示了如何(我知道你要求Objective-C – 但这太简单了):
编辑:代码也应该适用于UTF-16和UTF-32 – 具有任何字节顺序 – 如果编码器只是机械地做了我怀疑的,它也应该适用于转义的unicode字符,例如\ u1234等。
编辑 – 不,它不适用于UTF-16和UTF-32。 样本必须为此固定(这很容易)。 但请确保您拥有UTF-8 – 几乎总是如此。
#include char input[] = u8R"___({ \"name\" : \"Bob\", \"age\" : 21 })___"; // Unescapes the character sequence "in-situ". // Returns a pointer to "past-the-end" of the unescaped string. static char* unescape(char* first, char* last) { char* dest = first; while (first != last) { if (*first == '\\') { ++first; } *dest++ = *first++; } return dest; } int main(int argc, const char * argv[]) { char* first = input; char* last = first + strlen(input); std::string s(input, unescape(first, last)); std::cout << s << std::endl; return 0; }
打印:
{“name”:“Bob”,“age”:21}
- iPhone上的jQuery Mobile + PhoneGap无法加载页面
- MPMusicPlayerController setCurrentPlaybackRate
- 何时使用UICollectionView而不是UITableView?
- 更改默认“未选择”UITabBarItem图像颜色
- Xcode Server:iOS持续交付的XCS的十大限制
- 在Firebase和Swift 3中注册之前,如何validation用户名是否存在?
- 如何使用Cordova在iOS中永久存储数据?
- RainCat:第2课
- 当有很多使用阴影的UILabels运行的UIViewanimation时,设备会冻结,然后按Homebutton