将Swift字符串编码为转义的Unicode?

5

API数据字段仅支持ASCII编码,但我需要支持Unicode(表情符号、外文字符等)。

我想将用户输入的文本编码为转义的Unicode字符串:

let textContainingUnicode = """
Let's go  in the .
  And some new lines.
"""

let result = textContainingUnicode.unicodeScalars.map { $0.escaped(asASCII: true)}
  .joined(separator: "")
  .replacingOccurrences(
    of: "\\\\u\\{(.+?(?=\\}))\\}", <- converting swift format \\u{****}
    with: "\\\\U$1",               <- into format python expects
    options: .regularExpression)

result这里是"让我们在\U0001F3CA中去\U0001F30A。\n还有一些新行。"

在服务器端使用Python进行解码:

codecs.decode("让我们在\\U0001F3CA中去\\U0001F30A。\\n还有一些新行。\n", 'unicode_escape')

但这听起来有些奇怪——我真的需要在Swift中进行如此多的字符串操作才能获得转义的Unicode吗?这些格式在不同的语言中是否都是标准化的。


为什么不能直接将原始字符串发送到服务器?Unicode本身就是“标准化格式”。 - matt
这是AWS的限制:“用户定义的元数据是一组键值对。Amazon S3将用户定义的元数据键存储为小写。每个键值对在使用REST时必须符合US-ASCII,在使用SOAP或基于浏览器的POST上传时必须符合UTF-8。”他们不再使用SOAP客户端,我想我可以自己编写。https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html - tgk
1个回答

5
你可以在集合中使用reduce函数,检查每个字符是否为ASCII码。如果是,则返回该字符;否则将特殊字符转换为Unicode编码:

Swift 5.1 • Xcode 11

extension Unicode.Scalar {
    var hexa: String { .init(value, radix: 16, uppercase: true) }
}

extension Character {
    var hexaValues: [String] {
        unicodeScalars
            .map(\.hexa)
            .map { #"\\U"# + repeatElement("0", count: 8-$0.count) + $0 }
    }
}

extension StringProtocol where Self: RangeReplaceableCollection {
    var asciiRepresentation: String { map { $0.isASCII ? .init($0) : $0.hexaValues.joined() }.joined() }
}

let textContainingUnicode = """
Let's go  in the .
  And some new lines.
"""

let asciiRepresentation = textContainingUnicode.asciiRepresentation
print(asciiRepresentation)  // "Let's go \\U0001F3CA in the \\U0001F30A.\n  And some new lines."

如果您要使用Swift 5,您可以使用新的非逃逸字符串文字,并摆脱一些反斜杠。 - matt
1
谢谢Leo,学习创建utf-8字符串的逻辑很酷。我接受这个答案,感谢您的耐心。 - tgk
1
很好!谢谢Leo。 - user5568766

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接