4

我有一堆文件保存在 Apache Lucene 中,其中一些名称是俄语,当我尝试将它们打印出来时,它看起来像这样"\u0410\u0441\u043f\u0430\u0440",但不是西里尔符号。该项目在Scala中。我尝试使用 Apache CommonsunescapeJava方法解决此问题,但没有帮助。还有其他选择吗?

更新: 项目是用 Spray 框架编写的,并像这样返回 json。

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

2 回答 2

8

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

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

请参阅此处的定义printStringhttps ://github.com/spray/spray-json/blob/master/src/main/scala/spray/json/JsonPrinter.scala

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

作为旁注,值得一提的是,json 规范并没有规定字符的编码方式:它们可以存储为文字值,也可以存储为 unicode 转义。例如,字符串"abc"可以描述为 just"abc"或 as "\u0061\u0062\u0063"。任何一种形式都是正确的。恰好 spray-json 的作者决定对所有非 ascii 字符使用后一种形式。

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

最简单的做法是将对象转换为字符串(通过JsValue.toStringorJsValue.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 转义。

于 2013-02-13T14:46:08.913 回答
0

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

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

于 2015-11-03T17:44:42.697 回答