NSJSONSerialization对包含正斜杠的字符串进行序列化,并且/ / HTML被错误地转义

问题描述 投票:10回答:3

[我正在尝试将一些简单的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在序列化时转义字符串值中的正斜杠。

ios json nsstring nsjsonserialization nsstringencoding
3个回答
4
投票

我相信NSJSONSerialization的行为与设计HTML编码有关。

[如果您看到有关以JSON编码HTML的一些问题(12),您将看到答案总是提到转义正斜杠。

[JSON不需要转义斜线,但是HTML不允许JavaScript字符串包含</,因为它可能与<SCRIPT>标记的末尾混淆。

请参阅答案herehere,最直接是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>标签中使用的规则播放。


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

0
投票

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

示例:

jsonData = [NSJSONSerialization dataWithJSONObject:batchUpdates
                                           options:NSJSONWritingWithoutEscapingSlashes
                                             error:nil];
© www.soinside.com 2019 - 2024. All rights reserved.