虽然JSON spec 不允许将键值对序列化为 JSON 数组,但您可以使用 Map[String, String] 的自定义编解码器将其归档为 jsoniter-scala。
- 为您的构建添加依赖项:
libraryDependencies ++= Seq(
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "2.6.0",
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.6.0" % "provided" // it is required only in compile-time
)
- 导入
core 和macros 模块:
import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._
- 通过所需的注释来扩充您的数据结构(这里
@named 用于更改fun_facts 字段的键):
case class Person(name: String, @named("fun facts") fun_facts: Map[String, String])
- 为
Map 创建一个自定义编解码器并为Person 派生一个编解码器:
implicit val mapCodec: JsonValueCodec[Map[String, String]] = new JsonValueCodec[Map[String, String]] {
override def decodeValue(in: JsonReader, default: Map[String, String]): Map[String, String] =
if (in.isNextToken('[')) {
if (in.isNextToken(']')) default
else {
in.rollbackToken()
val mb = Map.newBuilder[String, String]
var i = 0
while ({
mb += ((in.readKeyAsString(), in.readString(null)))
i += 1
if (i > 100000) { // a safe limit to avoid DoS attacks, see https://github.com/scala/bug/issues/11203
in.decodeError("too many map inserts")
}
in.isNextToken(',')
}) ()
if (in.isCurrentToken(']')) mb.result()
else in.arrayEndOrCommaError()
}
} else in.readNullOrTokenError(default, '[')
override def encodeValue(kvs: Map[String, String], out: JsonWriter): Unit = {
out.writeArrayStart()
kvs.foreach { case (k, v) =>
out.writeKey(k)
out.writeVal(v)
}
out.writeArrayEnd()
}
override val nullValue: Map[String, String] = null
}
implicit val personCodec: JsonValueCodec[Person] = JsonCodecMaker.make
- 使用它们进行解析和序列化:
val json = """{
| "name": "John Doe",
| "fun facts" : [
| "favorite_food": "pizza",
| "hobby": "running"
| ]
|}""".stripMargin.getBytes("UTF-8")
val person = readFromArray[Person](json)
println(person)
println()
println(new String(writeToArray(person, config = WriterConfig.withIndentionStep(4)), "UTF-8"))
预期输出:
Person(John Doe,Map(favorite_food -> pizza, hobby -> running))
{
"name": "John Doe",
"fun facts": [
"favorite_food": "pizza",
"hobby": "running"
]
}