在Scala中创建Json数组

时间:2016-03-08 17:28:37

标签: java json scala

我试图像这样创建一个Json对象



{
  "Field1": [{}, {}, {}, {}],
  "Field2": [{}, {}, {}],
  "Field3": {}
}




通常在Java中我可以通过(特别是使用google simple json)来实现这一目标

  1. 为field1和field2创建JSON数组,
  2. 为Field3创建JSON对象
  3. 将上述3组合成另一个JSONObject
  4. 上面的结果来自不同的进程,我需要返回一个组合的json对象

    我很困惑如何在Scala中实现相同的功能,我尝试了多种库和方法。我最近尝试的是json4s。我以为我可以

    1. 遍历一个字符串列表并将它们放入" json数组"
    2. 将上面的数组添加到另一个" json对象"用钥匙
    3. 返回组合的json对象
    4. 我认为这会像在Java中一样简单,我错过了一些明显的东西吗? (我是斯卡拉新手)。

      非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

以下是在circe中执行此操作的一种方法:

import io.circe.syntax._

val json = Map(
  "Field1" -> List.fill(4)(()).asJson,
  "Field2" -> List.fill(3)(()).asJson,
  "Field3" -> ().asJson
).asJson

然后:

scala> json.noSpaces
res0: String = {"Field1":[{},{},{},{}],"Field2":[{},{},{}],"Field3":{}}

这里有几点需要注意。第一个是Scala鼓励使用不可变集合,因此不使用“将值放入”列表,而是使用List.fill(n)(value)之类的实用程序,它会创建value重复n次列表。这意味着List.fill(3)(())List((), (), ())完全相同,我们也可以在上面使用它。

第二点更具针对性。 ()是Scala中的一个特殊值 - 它是类型Unit的唯一值,它只代表一个不带信息的空事物。在()中,{}的JSON编码为().asJson,因此我们可以通过调用List.fill(3)(()).asJson来创建一个空的JSON对象。

circe也知道如何从它知道如何编码的任何类型的Scala列表(或其他序列)中创建一个JSON数组,因此Map是一个JSON值,它是一个三个空JSON的JSON数组对象。

最后,circe还知道如何从Scala Map[String, io.circe.Json]创建一个JSON对象,其中键是字符串,值类型是它知道如何编码的东西。这意味着我们可以创建一个asJson类型的地图,并在其上调用case class Fields(Field1: List[Unit], Field2: List[Unit], Field3: Unit) 以获取一个JSON值,该值是一个包含地图所代表的字段的JSON对象。

根据您的确切用例,还有其他方法可以做到这一点,可能会更好,包括以下内容:

scala> import io.circe.generic.auto._
import io.circe.generic.auto._

scala> Fields(List((), (), (), ()), List((), (), ()), ()).asJson.noSpaces
res0: String = {"Field1":[{},{},{},{}],"Field2":[{},{},{}],"Field3":{}}

然后:

{{1}}

这种方法(使用circe对generic codec derivation的支持)通常比直接使用JSON值更惯用。

答案 1 :(得分:1)

我使用scala module with jackson,JsonUtil.scala:

package json

import com.fasterxml.jackson.databind.{SerializationFeature, DeserializationFeature, ObjectMapper, PropertyNamingStrategy}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

object JsonUtil {
  private val ObjectMapper = buildMapper()

  private def buildMapper() = {
    val mapper = new ObjectMapper() with ScalaObjectMapper
    mapper.registerModule(DefaultScalaModule)
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    mapper.enable(SerializationFeature.INDENT_OUTPUT)
    mapper
  }

  def fromJson[A](json: String, objectType: Class[A]): A = {
    ObjectMapper.readValue(json, objectType)
  }

  def toJson(data: AnyRef): String = {
    ObjectMapper.writeValueAsString(data)
  }
}

依赖关系:

compile 'com.fasterxml.jackson.core:jackson-core:2.6.3'
compile 'com.fasterxml.jackson.module:jackson-module-scala_2.11:2.6.3'

然后,它易于使用:

case class MyDto(id: Int, name: Option[String])
...
val jsonString = JsonUtil.toJson(MyDto(123, Some("John Doe")))
val dto = JsonUtil.fromJson(jsonString, classOf[MyDto])

case class MyList(items: List[Int])
...
val jsonList = JsonUtil.toJson(MyList(List(1,2,3,4,5)))

答案 2 :(得分:0)

虽然有点冗长,但您可以使用play framework。这使得能够编写案例类对象,然后直接将它们转换为JSON对象。以下示例有点松散,因为您没有说明您的对象究竟是什么样的。

case class ResponseObject(a: Field1, b: Field2, c: Field3)
case class Field1(a: Seq[Field1obj])
case class Field2(a: Seq[Field2obj]))
case class Field3(a: Field3obj)
case class Field1obj(a: String, b: Int)
...

然后你可以使用

编写一个隐式编写器
implicit val responseWrites = Json.writes[ResponseObject]
implicit val fieldWrites = Json.writes[Field1]
...
val resultToSend = ResponseObject(field1, field2, field3)
val json = Json.toJson(resultToSend)