2016-02-03 18 views
10

mam bardzo prosty przykład:Jak serializować JSON z json4s ze znakami UTF-8?

import org.json4s._ 
import org.json4s.native.JsonMethods._ 
import org.json4s.JsonDSL._ 

val json = ("english" -> JString("serialization")) ~ ("japanese" -> JString("シリアライゼーション")) 

println(pretty(render(json))) 

Co wyjdę z tego jest:

{ 
    "english":"serialization", 
    "japanese":"\u30b7\u30ea\u30a2\u30e9\u30a4\u30bc\u30fc\u30b7\u30e7\u30f3" 
} 

Co chcę to jest (całkowicie poprawny AFAIK) JSON:

{ 
    "english":"serialization", 
    "japanese":"シリアライゼーション" 
} 

Nie mogę go teraz znaleźć, ale myślę, że przeczytałem gdzieś, że JSON wymaga tylko dwóch specjalnych znaków UTF-8, aby uciec.

Patrząc na kod dla render, wydaje się, że Strings always get this extra double-escaping for non-ASCII characters.

Ktoś wie, w jaki sposób mogę uzyskać prawidłowy JSON bez podwójnego ucieczki wszystkich rozszerzonych znaków UTF-8? Wydaje się to bardzo podobnego problemu do: Why does the PHP json_encode function convert UTF-8 strings to hexadecimal entities?


Aktualizacji: Okazuje się, że jest to sprawa otwarta w json4s z oczekującym PR #327 który został zamknięty na rzecz PR #339 które z kolei połączone w wydaniu 3.4 oddział w commit on Feb 13, 2016.

+0

Nie wiem o _json4s_, ale [RFC 7159] (https://tools.ietf.org/html/rfc7159) mówi, że UTF-8 jest domyślnym kodowaniem dla JSON.Więc teoretycznie nie ma potrzeby (tylko opcja), aby uciec japońskie znaki. Potrzebujesz tylko biblioteki, która to robi lub która może być odpowiednio skonfigurowana. – kriegaex

Odpowiedz

6

@ 0__, to nie jest jasne, co odpowiedź chcesz się ze swojej dobroci. Błąd wspomniany w pierwotnym pytaniu został już naprawiony, więc możesz dostosować, czy chcesz kodować znaki Unicode, czy nie. Trzeba tylko zbudować z aktualną wersją, np. z build.sbt jak ten:

name := "SO_ScalaJson4sUnicodeChars" 
version := "1.0" 
scalaVersion := "2.12.1" 
libraryDependencies += "org.json4s" %% "json4s-native" % "3.5.1" 

As @kriegaex wspomniał w swoim komentarzu, UTF-8 jest domyślne kodowanie dla JSON zgodnie z RFC 7159, więc kodowanie nie jest to bezwzględnie konieczne. Dlatego domyślnie json4s nie koduje, podobnie jak PO o:

dziennik
package so 

import org.json4s.JsonDSL._ 
import org.json4s._ 
import org.json4s.native.JsonMethods._ 

object SOTest extends App { 
    val json = ("english" -> JString("serialization")) ~ ("japanese" -> JString("シリアライゼーション")) 
    println(pretty(render(json))) 
} 

konsoli:

{ 
    "english":"serialization", 
    "japanese":"シリアライゼーション" 
} 

Jednak jeśli z jakiegoś kompatybilności powodu trzeba wyjścia do encdeded, json4s również to popiera. Jeśli dodać własny customJsonFormats tak, można się zakodowane dane wyjściowe:

package so 

import org.json4s.JsonDSL._ 
import org.json4s._ 
import org.json4s.native.JsonMethods._ 

object SOTest extends App { 
    val json = ("english" -> JString("serialization")) ~ ("japanese" -> JString("シリアライゼーション")) 
    implicit val customJsonFormats = new DefaultFormats { 
    override def alwaysEscapeUnicode: Boolean = true 
    } 
    println(pretty(render(json))) 
} 

dziennik konsoli:

{ 
    "english":"serialization", 
    "japanese":"\u30b7\u30ea\u30a2\u30e9\u30a4\u30bc\u30fc\u30b7\u30e7\u30f3" 
} 

aktualizację @kriegaex: postanowiłem edytować tę odpowiedź, połączenie niektórych informacji z mojej własnej i naprawienie kilku drobnych problemów. Zrobiłem to, aby uniknąć nadmiarowości. Bardziej interesuje mnie dobra, spójna odpowiedź niż w nagrodę. Teraz mam zamiar usunąć moje.

+0

Dzięki. Myślałem, że mam ten sam problem co OP, ale okazało się, że problem polegał na tym, że Wysłanie nie powracało do UTF-8, ale ISO Latin, gdy typ zawartości nie określał kodowania. –