无法将unicode符号转换为西里尔字母

时间:2013-02-13 12:00:19

标签: scala unicode escaping spray spray-json

我有一堆文件在Apache Lucene中保留了俄语中的一些名字,当我试图将它们打印出来时,它看起来像"\u0410\u0441\u043f\u0430\u0440",但不是西里尔符号。该项目在Scala。我试图用Apache Commons unescapeJava方法修复此问题,但它没有帮助。还有其他选择吗?

更新 使用Spray框架编写Project并像这样返回json。

{
  "id" : 0,
  "name" : "\u0410\u0441\u043f\u0430\u0440"
}

2 个答案:

答案 0 :(得分:8)

我将尝试准确推断出你在做什么。 你正在使用Spray,所以我认为你正在使用它的json库“spray-json”

所以我想你有一些spray.json.JsObject的实例,你在问题中发布的是你在打印这个实例时得到的输出。 您的json对象是正确的,name字段的值没有嵌入转义,它实际上是转换为转义为转义某些unicode字符的字符串。

在此处查看printString的定义: https://github.com/spray/spray-json/blob/master/src/main/scala/spray/json/JsonPrinter.scala

我还假设您尝试使用unescapeJava时,将其应用于name字段的值,然后创建一个新的spray.json.JsObject实例,然后像之前一样打印。鉴于你的json对象实际上没有任何转义,这绝对没有什么,然后在打印时打印机像以前一样进行转义,然后你又回到原点。

作为旁注,值得一提的是json规范没有规定如何编码字符:它们既可以存储为文字值,也可以存储为unicode转义符。例如,字符串"abc"可以仅描述为"abc",或描述为"\u0061\u0062\u0063"。两种形式都是正确的。碰巧喷涂json的作者决定将后一种形式用于所有非ascii字符。

所以现在你问,我该怎么做才能解决这个问题?您可以要求spray-json作者添加一个选项,让您指定不需要任何unicode转义。 但我想你现在想要一个解决方案

最简单的方法是将对象转换为字符串(通过JsValue.toStringJsValue.compactPrintJsValue.prettyPrint),然后传递结果到unescapeJava。至少这会让你回到你的西里尔文原文字符。 但这有点严重,实际上非常危险,因为某些字符在字符串文字中不安全。例如:\n将取消转换为实际退货,\u0022将转义为"。您可以轻松地看到它将如何破坏您的json文档。 但至少它可以证实我的理论(记住我一直在假设你究竟在做什么)。

现在进行正确修复:您可以简单地扩展JsonPrinter并覆盖其printString方法以删除unicode转义。像这样(未经测试):

trait NoUnicodeEscJsonPrinter extends JsonPrinter {
  override protected def printString(s: String, sb: StringBuilder) {
    @tailrec
    def printEscaped(s: String, ix: Int) {
      if (ix < s.length) {
        s.charAt(ix) match {
          case '"' => sb.append("\\\"")
          case '\\' => sb.append("\\\\")
          case x if 0x20 <= x && x < 0x7F => sb.append(x)
          case '\b' => sb.append("\\b")
          case '\f' => sb.append("\\f")
          case '\n' => sb.append("\\n")
          case '\r' => sb.append("\\r")
          case '\t' => sb.append("\\t")
          case x => sb.append(x)
        }
        printEscaped(s, ix + 1)
      }
    }
    sb.append('"')
    printEscaped(s, 0)
    sb.append('"')
  }
}

trait NoUnicodeEscPrettyPrinter  extends PrettyPrinter with NoUnicodeEscJsonPrinter
object NoUnicodeEscPrettyPrinter extends NoUnicodeEscPrettyPrinter

trait NoUnicodeEscCompactPrinter   extends CompactPrinter  with NoUnicodeEscJsonPrinter
object NoUnicodeEscCompactPrinter  extends NoUnicodeEscCompactPrinter

然后你可以这样做:

val json: JsValue = ...
val jsonString: String = NoUnicodeEscPrettyPrinter( json )

jsonString将以漂亮的打印格式包含您的json文档,并且没有任何unicde转义。

答案 1 :(得分:0)

此问题似乎已在spray-json 1.3.2中得到纠正:https://github.com/spray/spray-json/issues/46

我使用Akka HTTP 1.0遇到类似的阿拉伯字符问题,这取决于1.3.1。通过升级到1.3.2,我的问题得到了解决。