2016-06-21 71 views
1

我正在Scala的Play Framework中的後端服務器上工作。但是,我調用返回Java列表(util.List)的外部庫(用java編寫)。我爲列表中包含的對象創建了寫入,但是我不知道如何爲實際列表寫入寫入,以便它可以是通用的(無需爲列表和列表寫入「寫入」只是A和B的寫入)。JSON寫入Java列表

我知道我可以使用JavaConversions將Java列表轉換爲Scala Seq(已經實現了Writes),但由於速度是必不可少的,我不想做額外的轉換。

回答

2

這裏是一個可能的實現

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]無論如何,所以你需要構建一個階Seq這種或那種方式。

我這裏顯示什麼是或多或少等同於使用asScala轉換的java List Scala的mutable.Buffer並使用默認WritesTraversable

請注意,轉換可能不像您想象的那樣廣泛,它們只是創建包裝,不涉及複製。

這是我能在性能

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毫秒)。

+0

謝謝。這正是我所期待的。 –

1

您可以編寫一個Writes是重用現有的斯卡拉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) 
}