如何使用带有 UTF-8 字符的 json4s 序列化 JSON?

Posted

技术标签:

【中文标题】如何使用带有 UTF-8 字符的 json4s 序列化 JSON?【英文标题】:How to serialize JSON with json4s with UTF-8 characters? 【发布时间】:2016-05-12 03:25:18 【问题描述】:

我有一个非常简单的例子:

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

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

println(pretty(render(json)))

我从中得到的是:


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

我想要的是这个(完全有效的 AFAIK)JSON:


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

我现在找不到它,但我想我在某处读到 JSON 只需要转义两个特殊的 UTF-8 字符。

查看render 的代码,似乎是Strings always get this extra double-escaping for non-ASCII characters。

任何人都知道如何在不双重转义所有 UTF-8 扩展字符的情况下获得有效的 JSON 吗?这似乎与以下问题非常相似:Why does the php json_encode function convert UTF-8 strings to hexadecimal entities?


更新:事实证明,这是 json4s 中的一个未解决问题,带有待处理的 PR #327,该问题已被关闭以支持 PR #339,而 PR #339 又合并到 @987654326 中的 3.4 发布分支@。

【问题讨论】:

我不知道 json4s,但是RFC 7159 说 UTF-8 是 JSON 的默认编码。所以理论上没有必要(只有一个选项)来转义日文字符。您只需要一个可以执行此操作或可以进行相应配置的库。 【参考方案1】:

@0__,目前尚不清楚你想用你的赏金得到什么答案。原始问题中提到的错误已经修复,因此您可以自定义是否要对 Unicode 字符进行编码。您只需要使用当前版本进行构建,例如像这样的build.sbt

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

正如 @kriegaex 在他的评论中提到的,根据 RFC 7159,UTF-8 是 JSON 的默认编码,因此编码并不是绝对必要的。这就是为什么默认情况下 json4s 不编码,就像 OP 要求的那样:

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)))

控制台日志:


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

但是,如果出于某种兼容性原因您需要对输出进行编码,那么 json4s 也支持。如果你像这样添加自己的customJsonFormats,你会得到编码输出:

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)))

控制台日志:


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


更新由 @kriegaex 我决定编辑这个答案,合并我自己的一些信息并修复一些小问题。我这样做是为了避免冗余。我对一个好的、一致的答案比对赏金更感兴趣。我现在要删除我的。

【讨论】:

谢谢。我以为我和 OP 有同样的问题,但发现问题实际上是 Dispatch 没有回退到 UTF-8 而是 ISO Latin 当内容类型没有指定编码时。

以上是关于如何使用带有 UTF-8 字符的 json4s 序列化 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Scala中使用Json4s序列化密封的抽象类?

怎么辨别文本文档的编码?

Scala中json格式字符串map相互转换

如何将带有中文字符的 CSV UTF-8 文件导入 MySQL?

刨根究底字符编码之十一——UTF-8编码方式与字节序标记

如何将带有“(ISO-8859-1)字符的字符串转换为普通(UTF-8)字符?