4

ロシア語でいくつかの名前を持つ Apache Lucene に永続化されたドキュメントの束があり、それらを印刷しようとすると、このように見えます"\u0410\u0441\u043f\u0430\u0440"が、キリル記号ではありません。プロジェクトはScalaです。Apache Commons の方法でこれを修正しようとしましたunescapeJavaが、役に立ちませんでした。他のオプションはありますか?

更新: プロジェクトは、Spray フレームワークで作成され、次のような json を返します。

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

2 に答える 2

8

私はあなたが何をしているのかを正確に推測しようとします。スプレーを使用しているので、そのjsonライブラリ「spray-json」を使用していると思います

のインスタンスがありspray.json.JsObject、質問に投稿したのは、このインスタンスを印刷するときに出力として得られるものだと思います。あなたのjsonオブジェクトは正しいです。nameフィールドの値にはエスケープが埋め込まれていません。実際には、一部のユニコード文字をエスケープする文字列への変換です。

ここの定義を参照してくださいprintString: https://github.com/spray/spray-json/blob/master/src/main/scala/spray/json/JsonPrinter.scala

また、 を使用しようとしたときに、それをフィールドunescapeJavaの値に適用して新しいインスタンスを作成し、それを以前と同じように出力したと仮定します。あなたのjsonオブジェクトに実際にはエスケープがないことを考えると、これは絶対に何もしませんでした。それを印刷すると、プリンターは以前と同じようにエスケープを行い、正方形に戻ります。namespray.json.JsObject

補足として、json 仕様は文字のエンコード方法を義務付けていないことに言及する価値があります。文字はリテラル値として、または Unicode エスケープとして格納できます。例として、文字列は just 、または as として"abc"記述できます。どちらの形式も正しいです。たまたま、spray-json の作成者が、ASCII 以外のすべての文字に後者の形式を使用することにしました。"abc""\u0061\u0062\u0063"

では、この問題を回避するにはどうすればよいでしょうか。スプレー json の作成者に、Unicode エスケープを望まないことを指定できるオプションを追加するよう依頼することができます。しかし、あなたは今すぐ解決策を望んでいると思います。

最も簡単な方法は、オブジェクトを (JsValue.toStringまたはJsValue.compactPrintまたはを介し​​てJsValue.prettyPrint)文字列に変換し、その結果を渡すことunescapeJavaです。少なくともこれにより、元のキリル文字が返されます。しかし、これは少しグロスであり、文字列リテラル内で安全にエスケープできない文字があるため、実際には非常に危険です。例:\nは実際の return にエスケープされず、 に\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ドキュメントがきれいな印刷形式で、ユニコードエスケープなしで含まれます。

于 2013-02-13T14:46:08.913 に答える
0

This problem appears to be corrected in spray-json 1.3.2: https://github.com/spray/spray-json/issues/46

I ran into a similar problem with Arabic characters using Akka HTTP 1.0, which depends on 1.3.1. By upgrading to 1.3.2, my problem was resolved.

于 2015-11-03T17:44:42.697 に答える