2013-02-13 62 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,我的問題得到解決。