我有一个需要处理来自网络服务的响应的iOS应用。响应是一个包含序列化JSON对象的序列化JSON字符串,如下所示:
"{ \"name\" : \"Bob\", \"age\" : 21 }"
请注意,此响应是JSON 字符串,而不是JSON对象。我需要做的是反序列化字符串,以便我得到这个:
{ "name" : "Bob", "age" : 21 }
然后我可以使用+[NSJSONSerialization JSONObjectWithData:options:error:]
将其反序列化为NSDictionary
。
但是,我该如何做到第一步?也就是说,我如何“unescape”字符串,以便我有一个序列化的JSON对象? +[NSJSONSerialization JSONObjectWithData:options:error:]
仅在顶级对象是数组或字典时有效;它不适用于字符串。
我最后写了my own JSON string parser,我希望这符合section 2.5 of RFC 4627。但我怀疑我使用NSJSONSerialization
或其他一些可用的方法忽略了一些简单的方法。
答案 0 :(得分:24)
如果你有嵌套的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; }
答案 1 :(得分:0)
将字符串转换为数据:
NSString *string = @"{ \"name\" : \"Bob\", \"age\" : 21 }";
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
答案 2 :(得分:0)
只需切断前导和尾随引号,然后将所有\“s替换为”:
NSString *sub = [original substringWithRange:(NSRange){ 1, original.length - 2 }];
NSString *unescaped = [sub stringByReplacingOccurrencesOfString:@"\\\" withString:@"\"];
答案 3 :(得分:0)
首先应该问一下,为什么服务器不包含JSON,作为子结构。
但无论如何。您获得的字符串似乎是转义 JSON。 实际意味着什么,完全取决于Web服务开发人员。我怀疑,只有双引号和一个转义本身已经通过转义\
进行了转义。生成的字符串不是“序列化” - JSON已经序列化 - 但编码。为了还原它 - 你需要再次“unescape”或解码:
一个小小的C ++代码段显示了(我知道你要求Objective-C - 但这太简单了):
编辑:代码也适用于UTF-16和UTF-32 - 具有任何字节顺序 - 如果编码器只是机械地做了我怀疑的,它也适用于转义的unicode字符,例如\ u1234等。
编辑 - 不,它不适用于UTF-16和UTF-32。样本必须为此固定(这很容易)。但请确保您拥有UTF-8 - 几乎总是如此。
#include <iostream>
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}