解析 Ruby 中的非花括号 unicode 表情符号
Parsing non-curly braced unicode emoji in Ruby
我从 API 收到一些我无法控制的文本。当我收到表情符号时,它们没有为 Ruby 正确编码。这是我收到的示例:
- 编码:“\u1F44C”
- 解码:“ὄC”
Ruby 不处理超过 4 个十六进制字符的 unicode,除非你使用大括号。所以 "\u{1F44C}" 会被正确解码为 .
如何将 API 的输出转换为 Ruby 可以正确解码的格式?
您在这里处理的是一个损坏的 API。这不是 Ruby 问题,而是 JSON 编码器问题。每 the JSON spec:
If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u
, followed by four hexadecimal digits that encode the character's code point. The hexadecimal letters A
though F
can be upper or lower case. So, for example, a string containing only a single reverse solidus character may be represented as "\u005C
".
...
To escape an extended character that is not in the Basic Multilingual Plane, the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair. So, for example, a string containing only the G clef character (U+1D11E) may be represented as "\uD834\uDD1E
".
所以 </code> 的正确编码应该是 <code>\uD83D\uDC4C
。任何兼容的 JSON 解析器都会产生与您所看到的相同的输出。您应该向 API 供应商报告错误——您几乎可以肯定不是他们遇到此问题的唯一客户。
如果您无法让 API 供应商修复他们的 API,除了实现您自己的 JSON 解析器(或放弃供应商)之外,您唯一的办法就是尝试使用正则表达式修复 JSON 响应。像这样的东西可行,但是 将 容易受到误报的影响,这意味着一些有效的 JSON 会被破坏:
require "json"
def mangle_json(str)
str.gsub(/\u([0-9a-f]{5,6})/i) do
begin
.to_i(16).chr(Encoding::UTF_8)
rescue RangeError
$&
end
end
end
bad_json = '{"text":"OK\u1F44C let me see."}'
puts JSON.parse(bad_json)["text"]
# => OKὄC let me see.
puts JSON.parse(mangle_json(bad_json))["text"]
# => OK let me see.
在 repl.it 上查看:https://repl.it/GnFp/1
我从 API 收到一些我无法控制的文本。当我收到表情符号时,它们没有为 Ruby 正确编码。这是我收到的示例:
- 编码:“\u1F44C”
- 解码:“ὄC”
Ruby 不处理超过 4 个十六进制字符的 unicode,除非你使用大括号。所以 "\u{1F44C}" 会被正确解码为 .
如何将 API 的输出转换为 Ruby 可以正确解码的格式?
您在这里处理的是一个损坏的 API。这不是 Ruby 问题,而是 JSON 编码器问题。每 the JSON spec:
If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter
u
, followed by four hexadecimal digits that encode the character's code point. The hexadecimal lettersA
thoughF
can be upper or lower case. So, for example, a string containing only a single reverse solidus character may be represented as "\u005C
"....
To escape an extended character that is not in the Basic Multilingual Plane, the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair. So, for example, a string containing only the G clef character (U+1D11E) may be represented as "
\uD834\uDD1E
".
所以 </code> 的正确编码应该是 <code>\uD83D\uDC4C
。任何兼容的 JSON 解析器都会产生与您所看到的相同的输出。您应该向 API 供应商报告错误——您几乎可以肯定不是他们遇到此问题的唯一客户。
如果您无法让 API 供应商修复他们的 API,除了实现您自己的 JSON 解析器(或放弃供应商)之外,您唯一的办法就是尝试使用正则表达式修复 JSON 响应。像这样的东西可行,但是 将 容易受到误报的影响,这意味着一些有效的 JSON 会被破坏:
require "json"
def mangle_json(str)
str.gsub(/\u([0-9a-f]{5,6})/i) do
begin
.to_i(16).chr(Encoding::UTF_8)
rescue RangeError
$&
end
end
end
bad_json = '{"text":"OK\u1F44C let me see."}'
puts JSON.parse(bad_json)["text"]
# => OKὄC let me see.
puts JSON.parse(mangle_json(bad_json))["text"]
# => OK let me see.
在 repl.it 上查看:https://repl.it/GnFp/1