[我正在尝试将一些简单的HTML转换为JSON对象中的字符串值,但在获取字符串编码以免在NSJSONSerialization中转义字符串时遇到了麻烦。
示例...我有一个包含一些基本HTML文本的字符串:
NSString *str = @"<html><body><p>Samples / Text</p></body></html>";
期望的结果是以HTML作为值的JSON:
{
"Title":"My Title",
"Instructions":"<html><body><p>Samples / Text</p></body></html>"
}
我正在使用标准技术将NSDictionary转换为包含JSON的NSString:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:str forKey:@"Instructions"];
[dict setObject:@"My Title" forKey:@"Title"];
NSError *err;
NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&err];
NSString *resultingString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", resultingString);
此方法产生的JSON有效,但是HTML的所有正斜杠均已转义:
{
"Title":"My Title",
"Instructions":"<html><body><p>Samples \/ Text<\/p><\/body><\/html>"
}
这将在指令JSON字符串中创建无效的HTML。
我想坚持使用NSJSONSerialization,因为我们在框架中的其他地方都使用了NSJSONSerialization,在被取消支持之前,我被烧死在切换到非Apple库之前。我尝试了许多不同的字符串编码,所有这些编码都逃脱了尖括号。
显然\ /是JavaScript中/字符的有效表示形式,这就是为什么正斜杠被转义的原因(甚至是StackOverflow文本编辑器也对其进行了转义)。看到:escaping json string with a forward slash?还有JSON: why are forward slashes escaped?。我只是不希望它那样做,而且似乎没有一种方法可以阻止iOS在序列化时转义字符串值中的正斜杠。
我相信NSJSONSerialization
的行为与设计HTML编码有关。
[如果您看到有关以JSON编码HTML的一些问题(1,2),您将看到答案总是提到转义正斜杠。
[JSON不需要转义斜线,但是HTML不允许JavaScript字符串包含</
,因为它可能与<SCRIPT>
标记的末尾混淆。
请参阅答案here,here,最直接是w3.org HTML4 Appendix中陈述的B.3.2 Specifying non-HTML data
ILLEGAL EXAMPLE:
The following script data incorrectly contains a "</" sequence (as part of "</EM>") before the SCRIPT end tag:
<SCRIPT type="text/javascript">
document.write ("<EM>This won't work</EM>")
</SCRIPT>
尽管此行为可能会给您造成问题,但NSJSONSerialisation
只是按照古老的编码HTML数据以便在<SCRIPT>
标签中使用的规则播放。
这是我的AFJSONRequestSerializer
的子类,用于在结果JSON中的\
符号之前删除/
;如果使用AFNetworking,则非常方便
class SanitizedAFJSONRequestSerializer: AFJSONRequestSerializer
{
override func requestBySerializingRequest(request: NSURLRequest!, withParameters parameters: AnyObject!, error: NSErrorPointer) -> NSURLRequest!
{
var request = super.requestBySerializingRequest(request, withParameters: parameters, error: error)
if let jsonData = request.HTTPBody
{
if let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) as? String
{
let sanitizedString = jsonString.stringByReplacingOccurrencesOfString("\\/", withString: "/", options: NSStringCompareOptions.CaseInsensitiveSearch, range:nil) as NSString
println("sanitized json string: \(sanitizedString)")
var mutableRequest = request.mutableCopy() as! NSMutableURLRequest
mutableRequest.HTTPBody = sanitizedString.dataUsingEncoding(NSUTF8StringEncoding)
request = mutableRequest
}
}
return request
}
}
仅适用于iOS 13:如果您不担心产生无效的HTML序列(如this answer中所述),则可以通过将选项NSJSONWritingWithoutEscapingSlashes
传递给序列化程序来禁用正斜杠转义。
示例:
jsonData = [NSJSONSerialization dataWithJSONObject:batchUpdates
options:NSJSONWritingWithoutEscapingSlashes
error:nil];