包含正斜杠/和HTML的字符串的NSJSONSerialization序列化未正确转义

时间:2013-04-03 17:55:42

标签: ios json nsstring nsjsonserialization nsstringencoding

我正在尝试将一些简单的HTML转换为JSON对象中的字符串值,但我无法使字符串编码无法转义NSJSONSerialization中的字符串。

示例...我有一个包含一些基本HTML文本的字符串:

NSString *str = @"<html><body><p>Samples / Text</p></body></html>";

期望的结果是JSON,HTML为值:

{
    "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,因为我们在框架中的其他地方都使用它,并且在切换到非Apple库之前我已被烧毁,因为它们得不到支持。我尝试了很多不同的字符串编码,所有字符串编码都逃脱了尖括号。

显然\ /是JavaScript中/字符的有效表示,这就是转义正斜杠的原因(即使StackOverflow文本编辑器也将其转义)。看到: escaping json string with a forward slash? 还有JSON: why are forward slashes escaped?。我只是不希望它这样做,似乎没有办法阻止iOS在序列化时转义字符串值中的正斜杠。

3 个答案:

答案 0 :(得分:4)

我相信NSJSONSerialization的行为与HTML编码一样。

如果你看一些关于用JSON编码HTML的问题(12),你会看到答案总是提到转义正斜杠。

JSON并不要求转义斜杠,但HTML不允许javascript字符串包含</,因为它可能会与{{{1}的结尾混淆1}}标签。

查看答案herehere以及最直接w3.org HTML4 Appendix

中列出的B.3.2 Specifying non-HTML data
<SCRIPT>

虽然此行为可能会给您带来问题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数据编码的古老规则进行播放。

答案 1 :(得分:0)

这是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
    }
}

答案 2 :(得分:0)

仅适用于iOS 13: 如果您不担心产生无效的HTML序列(如this answer中所述),可以通过将选项NSJSONWritingWithoutEscapingSlashes传递给序列化程序来禁用正斜杠转义。

示例:

jsonData = [NSJSONSerialization dataWithJSONObject:batchUpdates
                                           options:NSJSONWritingWithoutEscapingSlashes
                                             error:nil];