简体   繁体   English

在 Scala 中创建一个 Json 数组

[英]Creating a Json array in Scala

I'm trying to create a Json object like so我正在尝试像这样创建一个 Json 对象

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

Typically in Java I could achieve this by (specifically using google simple json)通常在 Java 中,我可以通过(特别是使用 google simple json)来实现这一点

  1. Creating JSON arrays for field1 and field2,为 field1 和 field2 创建 JSON 数组,
  2. Creating a JSON Object for Field3为 Field3 创建 JSON 对象
  3. Combine the above 3 into another JSONObject将上面的3个组合成另一个JSONObject

The results for the above are coming from separate processes, I need to return a combined json object以上结果来自不同的进程,我需要返回一个组合的 json 对象

I'm confused how to achieve the same in Scala, I tried multiple libraries and approaches.我很困惑如何在 Scala 中实现相同的目标,我尝试了多种库和方法。 The latest I'm trying is json4s.我正在尝试的最新版本是 json4s。 I thought I could我以为我可以

  1. Iterate through a list of string and put them in a "json array"遍历字符串列表并将它们放入“json 数组”中
  2. Add the above array into another "json object" with a key使用键将上述数组添加到另一个“json 对象”中
  3. Return the combined json object返回组合的 json 对象

I thought this will be as straightforward as it is in Java, am I missing something obvious?我认为这会像在 Java 中一样简单,我是否遗漏了一些明显的东西? (I am Scala newbie). (我是 Scala 新手)。

Any help would be much appreciated.任何帮助将非常感激。

I use scala module with jackson , JsonUtil.scala:我将scala 模块与 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)
  }
}

Dependencies:依赖项:

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

Then, it's easy to use:然后,它很容易使用:

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)))

Here's one way to do this in circe :这是在circe 中执行此操作的一种方法:

import io.circe.syntax._

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

And then:进而:

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

There are a couple of things to note here.这里有几点需要注意。 The first is that Scala encourages the use of immutable collections, so instead of "putting values into" a list, you use utilities like List.fill(n)(value) , which creates a list of value repeated n times.第一个是 Scala 鼓励使用不可变集合,因此不是“将值放入”列表,而是使用List.fill(n)(value)类的实用程序,它创建一个重复n次的value列表。 This means List.fill(3)(()) is exactly the same as List((), (), ()) , which we could also have used above.这意味着List.fill(3)(())List((), (), ())完全相同,我们也可以在上面使用。

The second point is more circe-specific.第二点是更特定于 circe 的。 () is a special value in Scala—it's the only value of type Unit , which just represents an empty thing that carries no information. ()是 Scala 中的一个特殊值——它是Unit类型的唯一值,它只代表一个不携带任何信息的空东西。 In circe the JSON encoding of () is {} , so we can create an empty JSON object by calling ().asJson .实际上()的 JSON 编码是{} ,因此我们可以通过调用().asJson来创建一个空的 JSON 对象。

circe also knows how to create a JSON array out of a Scala list (or other sequence) of any type that it knows how to encode, so List.fill(3)(()).asJson is a JSON value that's a JSON array of three empty JSON objects. circe 还知道如何从它知道如何编码的任何类型的 Scala 列表(或其他序列)中创建一个 JSON 数组,所以List.fill(3)(()).asJson是一个 JSON 值,它是一个 JSON 数组三个空的 JSON 对象。

Lastly, circe also knows how to create a JSON object out of a Scala Map where the keys are strings and the value type is something it knows how to encode.最后,circe 还知道如何从 Scala Map创建一个 JSON 对象,其中键是字符串,值类型是它知道如何编码的东西。 This means we can create a map of type Map[String, io.circe.Json] and call asJson on it to get a JSON value that's a JSON object containing the fields represented by the map.这意味着我们可以创建一个Map[String, io.circe.Json]类型的Map[String, io.circe.Json]并在其上调用asJson以获取一个 JSON 值,该值是一个包含由映射表示的字段的 JSON 对象。

There are other ways you could do this in circe that might be nicer depending on your exact use case, including the following:根据您的具体用例,还有其他方法可以在 circe 中执行此操作,这些方法可能会更好,包括以下内容:

case class Fields(Field1: List[Unit], Field2: List[Unit], Field3: Unit)

And then:进而:

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

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

This approach (which uses circe's support for generic codec derivation ) is typically more idiomatic than working with JSON values directly.这种方法(使用 circe 对通用编解码器派生的支持)通常比直接使用 JSON 值更惯用。

While a little verbose you can use the play framework .虽然有点冗长,但您可以使用播放框架 This enables to write case class objects and then directly convert them into JSON objects.这允许编写案例类对象,然后直接将它们转换为 JSON 对象。 The following example is a little loose since you didn't say what exactly your objects look like.以下示例有点松散,因为您没有说明对象的确切外观。

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)
...

Then you can write an implicit writer using然后你可以使用

implicit val responseWrites = Json.writes[ResponseObject]
implicit val fieldWrites = Json.writes[Field1]
...
val resultToSend = ResponseObject(field1, field2, field3)
val json = Json.toJson(resultToSend)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM