JSON 写入 Java 列表

Posted

技术标签:

【中文标题】JSON 写入 Java 列表【英文标题】:JSON Writes for Java List 【发布时间】:2016-06-21 07:35:43 【问题描述】:

我正在使用 Scala 的 Play Framework 开发后端服务器。但是,我正在调用一个返回 Java 列表 (util.List) 的外部库(用 java 编写)。我为列表中包含的对象创建了一个写入,但是我不知道如何为实际列表编写写入,以便它可以是通用的(无需为列表和列表编写“写入”,只是 A 和 B 的写入)。

我知道我可以使用 JavaConversions 将 Java 列表转换为 Scala Seq(已经实现了 Writes),但由于速度至关重要,我不想进行额外的转换。

【问题讨论】:

【参考方案1】:

这是一个可能的实现

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],所以你需要以一种或另一种方式构造一个scalaSeq

我在这里展示的内容或多或少等同于使用 asScala 将 java List 转换为 scala mutable.Buffer 并将默认 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)
  

1000000 Ints 需要 29 毫秒,而直接实现需要 39 毫秒。请注意,Int 很容易转换,如果您的对象更复杂,则加速会更小。

转换其中的 20000 个 case class C(num: Int, n2: Int, s: String) 会得到相同的结果(直接速度甚至快 0.14 毫秒)。

【讨论】:

谢谢。这正是我想要的。【参考方案2】:

您可以编写一个 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) 

【讨论】:

以上是关于JSON 写入 Java 列表的主要内容,如果未能解决你的问题,请参考以下文章

如何将每个 Json 属性写入没有其内容的列表

无法写入 JSON:无法延迟初始化角色集合

python写入json文件

将整个列表写入java中的文件

Apache Beam:将具有对象列表的对象转换为多个 TableRows 以写入 BigQuery

将文本文件内容写入 Java 中的自定义数组列表