2013-02-13 151 views
4

我有一堆文件在俄文中以一些名字保存在Apache Lucene中,当我试图将它们打印出来时,它看起来像这样"\u0410\u0441\u043f\u0430\u0440",但不是西里尔文符号。该项目在斯卡拉。我试图用Apache Commons unescapeJava方法解决这个问题,但它没有帮助。还有其他选择吗?无法将Unicode符号转换为西里尔文

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

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

'Аспар',这是你期望的输出吗?因为对我来说,它工作。确保你用'UTF-16'编码 – Danyel 2013-02-13 12:10:14

+0

@Danyel是的,一般来说,但这只是一个例子 – 4lex1v 2013-02-13 12:47:39

+0

这不是清楚这是实际的字符串内容,还是仅仅是打印时执行某些转义的结果。你能告诉我们什么'println(theString.length)'打印?如果它是'5',那么问题不在于字符串,而是与它显示的方式有关。 – 2013-02-13 13:18:27

回答

7

我将尽力推测你在做什么。 您使用喷雾,所以我推测,您使用的是它的JSON库“喷雾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转义。例如,字符串​​可以被描述为仅仅是​​,或者被描述为"\u0061\u0062\u0063"。任何一种形式都是正确的。恰巧喷雾JSON的作者决定对所有非A​​SCII字符使用后一种形式。

所以,现在你问,我能做些什么来解决这个问题?您可以要求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将包含在美丽的打印格式,没有任何unicde逃脱你的JSON文件。

+1

+1非常好的答案和优秀的心灵感应能力:) – 4e6 2013-02-13 18:57:10

+0

感谢您的答案=)你是对的,但我们希望在浏览器端转换它们 – 4lex1v 2013-02-15 09:18:40

0

此问题出现在喷雾JSON 1.3.2将被校正:https://github.com/spray/spray-json/issues/46

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