Вот возможная реализация
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
один так или иначе.
Что показано здесь более или менее эквивалентно преобразования Java List
в Скале mutable.Buffer
используя asScala
и использование по умолчанию Writes
для Traversable
.
Обратите внимание, что конверсии, вероятно, не столь экспансивны, как вы думаете, они просто создают оболочку, а не копирование.
Вот лучшее, что я мог бы прийти с точки зрения производительности
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)
}
}
Это занимает 29 мс для 1000000 Int
с по сравнению с 39 мс для прямой реализации. Обратите внимание, что Int
легко конвертировать, если ваши объекты более сложны, ускорение будет меньше.
Преобразование 20000 из этих case class C(num: Int, n2: Int, s: String)
дает равные результаты (прямое ускорение на 0,14 мс).
Спасибо. Это именно то, что я искал. –