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

joh*_*ino 2 ruby unicode json emoji

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

  • 编码:“\u1F44C”
  • 解码:“?C”

除非您使用花括号,否则 Ruby 不会处理超过 4 个十六进制字符的 unicode。所以 "\u{1F44C}" 将被​​正确解码为 .

如何将 API 的输出转换为 Ruby 可以正确解码的格式?

Jor*_*ing 5

你在这里处理的是一个损坏的 API。这不是 Ruby 问题,而是 JSON 编码器问题。根据JSON 规范

如果字符在基本多语言平面(U+0000 到 U+FFFF)中,那么它可以表示为一个六字符序列:一个反实线,后跟小写字母u,后跟四个编码字符的十六进制数字代码点。十六进制字母A虽然F可以是大写或小写。因此,例如,仅包含单个反斜线字符的字符串可以表示为“ \u005C”。

...

为了对不在基本多语言平面中的扩展字符进行转义,该字符表示为 12 个字符的序列,对 UTF-16 代理项对进行编码。因此,例如,仅包含 G 谱号字符 (U+1D11E) 的字符串可以表示为“ \uD834\uDD1E”。

所以正确的编码\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
      $1.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.
Run Code Online (Sandbox Code Playgroud)

在 repl.it 上查看:https ://repl.it/GnFp​​/1