解析 Ruby 中的非花括号 unicode 表情符号

Parsing non-curly braced unicode emoji in Ruby

我从 API 收到一些我无法控制的文本。当我收到表情符号时,它们没有为 Ruby 正确编码。这是我收到的示例:

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