2013-02-13 5 views
4

저는 러시아어로 된 일부 이름으로 아파치 루씬에 보관 된 문서들을 많이 가지고 있는데,이를 인쇄하려고 할 때 키릴 문자가 아닌 "\u0410\u0441\u043f\u0430\u0440"처럼 보입니다. 프로젝트는 스칼라에 있습니다. 나는이 문제를 Apache Commons unescapeJava 방법으로 해결하려했지만 도움이되지 못했습니다. 다른 옵션이 있습니까?유니 코드 기호를 키릴 문자로 변환 할 수 없습니다.

업데이트 : 프로젝트가 스프레이 프레임 워크로 작성되고 json을 이와 같이 반환합니다.

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

'Аспар', 이것이 예상되는 출력입니까? 왜냐하면 나에게 그것은 효과가 있기 때문이다. 'UTF-16'으로 인코딩했는지 확인하십시오 – Danyel

+0

@Danyel 예, 일반적입니다. 그러나 이것은 단지 예일뿐입니다. – 4lex1v

+0

이것이 실제 문자열 내용인지 아니면 인쇄 할 때 수행되는 일부 이스케이프 결과인지는 분명하지 않습니다. 'println (theString.length)'이 출력하는 것을 우리에게 말해 줄 수 있습니까? '5'이면 문제는 문자열이 아니라 표시 방법과 관련됩니다. –

답변

7

나는 당신이하는 일을 정확히 추측하려고 노력할 것입니다. 당신은 스프레이를 사용하고, 그래서 그래서 난 당신이 spray.json.JsObject의 일부 인스턴스가 있다고 가정 나는 당신의 JSON 라이브러리 "스프레이 JSON"

를 사용하고 있는지 수집, 당신은 당신의 질문에 게시 무슨 당신이로 무엇을 얻을 이 인스턴스를 인쇄 할 때 출력. json 개체가 정확합니다. name 필드의 값에 포함 된 이스케이프가 없습니다. 실제로 유니 코드 문자를 이스케이프하는 문자열로 변환됩니다.

여기 printString의 정의를 참조하십시오 https://github.com/spray/spray-json/blob/master/src/main/scala/spray/json/JsonPrinter.scala

나는 또한 당신이 unescapeJava을 사용하려고 할 때, 당신은 당신이 다음과 같이 인쇄 새로운 spray.json.JsObject 인스턴스를 창조하는 name 필드의 값에 적용한다고 가정합니다 전에. 귀하의 JSON 개체가 실제로 어떤 도피가 없다는 것을 감안할 때, 이것은 절대적으로 아무것도하지 않았고, 프린터를 인쇄 할 때 이전처럼 이스케이프 처리를 수행하고 사각형으로 돌아 왔습니다.

참고로, json 사양은 문자가 인코딩되는 방식을 요구하지 않는다는 점을 언급 할 필요가 있습니다. 문자 그대로 리터럴 값 또는 유니 코드 이스케이프로 저장할 수 있습니다. 예를 들어 "abc" 문자열은 "abc" 또는 "\u0061\u0062\u0063"으로 설명 할 수 있습니다. 어느 형식이든 정확합니다. 스프레이 - json의 저자는 ASCII가 아닌 모든 문자에 대해 후자의 형식을 사용하기로 결정했습니다.

그럼 이제이 문제를 해결하려면 어떻게해야합니까? 스프레이 - json 작성자에게 유니 코드를 이스케이프하고 싶지 않음을 지정하는 옵션을 추가하도록 요청할 수 있습니다. 하지만 솔루션을 원한다고 상상해보십시오 . 할

가장 간단한 것은 다음는 unescapeJava에 결과를 전달 단지 (JsValue.toString 또는 JsValue.compactPrint 또는 JsValue.prettyPrint를 통해) 문자열로 개체를 변환하는 것입니다, 그리고 . 적어도 이것은 키릴 문자의 원래 문자를 돌려 줄 것입니다. 그러나 약간의 문자가 문자열 리터럴 내부에서 이스케이프하는 것이 안전하지 않기 때문에 이것은 약간 심하고 실제로 매우 위험합니다. 예 : \n은 실제 수익으로 이스케이프 처리되지 않으며 \u0022"으로 이스케이프 처리되지 않습니다. json 문서가 어떻게 손상되는지 쉽게 볼 수 있습니다. 하지만 적어도 내 이론을 확인할 수 있습니다 (내가 정확히 무엇을하고 있는지에 대한 가정을하고 있음을 기억하십시오).

올바른 해결 방법은 다음과 같습니다. JsonPrinter을 확장하고 printString 메서드를 재정 의하여 유니 코드 탈출을 제거 할 수 있습니다.이 (안된) 식으로 뭔가 :

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

+0

답변 해 주셔서 감사합니다.) 당신이 옳았지 만, 우리는 그들을 브라우저 측에서 변환해야했습니다. – 4lex1v

0

이 문제는 스프레이 JSON 1.3.2에서 수정 될 것으로 보인다 : 나는 1.3.1에 따라 Akka의 HTTP 1.0을 사용하여 아랍어 문자와 비슷한 문제로 실행 https://github.com/spray/spray-json/issues/46

. 1.3.2로 업그레이드하면 문제가 해결되었습니다.

관련 문제