JSON 为 Java 列表写入
JSON Writes for Java List
我正在使用 Scala 的 Play Framework 开发后端服务器。但是,我正在调用一个外部库(用 java 编写)returns 一个 Java 列表 (util.List)。我为列表中包含的对象创建了一个写入,但是我不知道如何为实际列表编写写入以便它可以是通用的(不需要为列表和列表,仅写入 A 和 B)。
我知道我可以使用 JavaConversions 将 Java 列表转换为 Scala Seq(已经实现了 Writes),但由于速度至关重要,我不想这样做额外转换。
您可以编写一个 Writes
重用 Scala 现有代码的代码 List
import java.util.{ List => JList }
implicit def JListWrites[T](implicit sw: Writes[List[T]]): Writes[JList[T]]) = Write[JList[T]] { jlist =>
sw.writes(jlist.asScala)
}
这是一个可能的实现
import play.api.libs.json.{JsArray, JsValue, Json, Writes}
import scala.collection.JavaConverters._
implicit def jListWrites[A: Writes] = new Writes[java.util.List[A]] {
override def writes(o: util.List[A]): JsValue = {
JsArray(o.asScala.map(Json.toJson(_)))
}
}
您创建的不是单个 Writes
,而是可以为定义了 Writes
的任何类型创建它们的方法。
你说你想避免 JavaConversions
,但正如你所看到的那样很难,因为 JsArray
无论如何都期望 Seq[JsValue]
所以你需要构建一个 scala Seq
一种或另一种方式。
我在这里展示的内容或多或少等同于使用 asScala
将 java List
转换为 scala mutable.Buffer
并为 [= 使用默认 Writes
22=].
请注意,转换可能没有您想象的那么广泛,它们只是创建一个包装器,不涉及复制。
这是我所能提供的最好的性能
implicit def jListWrites[A: Writes] = new Writes[java.util.List[A]] {
override def writes(o: util.List[A]): JsValue = {
val buffer = new Array[JsValue](o.size)
var i = 0
while (i < o.size) {
buffer(i) = Json.toJson(o.get(i))
i += 1
}
JsArray(buffer)
}
}
1000000 Int
秒需要 29 毫秒,而直接实现需要 39 毫秒。请注意 Int
很容易转换,如果您的对象更复杂,加速比会更小。
转换其中的 20000 个 case class C(num: Int, n2: Int, s: String)
得到相同的结果(直接更快 0.14 毫秒)。
我正在使用 Scala 的 Play Framework 开发后端服务器。但是,我正在调用一个外部库(用 java 编写)returns 一个 Java 列表 (util.List)。我为列表中包含的对象创建了一个写入,但是我不知道如何为实际列表编写写入以便它可以是通用的(不需要为列表和列表,仅写入 A 和 B)。
我知道我可以使用 JavaConversions 将 Java 列表转换为 Scala Seq(已经实现了 Writes),但由于速度至关重要,我不想这样做额外转换。
您可以编写一个 Writes
重用 Scala 现有代码的代码 List
import java.util.{ List => JList }
implicit def JListWrites[T](implicit sw: Writes[List[T]]): Writes[JList[T]]) = Write[JList[T]] { jlist =>
sw.writes(jlist.asScala)
}
这是一个可能的实现
import play.api.libs.json.{JsArray, JsValue, Json, Writes}
import scala.collection.JavaConverters._
implicit def jListWrites[A: Writes] = new Writes[java.util.List[A]] {
override def writes(o: util.List[A]): JsValue = {
JsArray(o.asScala.map(Json.toJson(_)))
}
}
您创建的不是单个 Writes
,而是可以为定义了 Writes
的任何类型创建它们的方法。
你说你想避免 JavaConversions
,但正如你所看到的那样很难,因为 JsArray
无论如何都期望 Seq[JsValue]
所以你需要构建一个 scala Seq
一种或另一种方式。
我在这里展示的内容或多或少等同于使用 asScala
将 java List
转换为 scala mutable.Buffer
并为 [= 使用默认 Writes
22=].
请注意,转换可能没有您想象的那么广泛,它们只是创建一个包装器,不涉及复制。
这是我所能提供的最好的性能
implicit def jListWrites[A: Writes] = new Writes[java.util.List[A]] {
override def writes(o: util.List[A]): JsValue = {
val buffer = new Array[JsValue](o.size)
var i = 0
while (i < o.size) {
buffer(i) = Json.toJson(o.get(i))
i += 1
}
JsArray(buffer)
}
}
1000000 Int
秒需要 29 毫秒,而直接实现需要 39 毫秒。请注意 Int
很容易转换,如果您的对象更复杂,加速比会更小。
转换其中的 20000 个 case class C(num: Int, n2: Int, s: String)
得到相同的结果(直接更快 0.14 毫秒)。