Scala:如何创建一个简单的嵌套 JSON 对象

Scala: How to create a simple nested JSON object

在 Scala 中,我想创建一个 JSON 对象或 JSON 字符串,其结果与此类似(即相对基本的嵌套 JSON):

{
   "info":{
      "info1":"1234",
      "info2":"123456",
      "info3":false
   },
   "x":[
      {
         "x1_info":10,
         "x2_info":"abcde"
      }
   ],
   "y":[
      {
         "y1_info":"28732",
         "y2_info":"defghi",
         "y3_info":"1261",
         "y_extra_info":[
            {
               "Id":"543890",
               "ye1":"asdfg",
               "ye2":"BOOLEAN",
               "ye3":false,
               "ye4":true,
               "ye5":true,
               "ye6":0,
               "ye7":396387
            }
         ]
      }
   ]
}

我计划在测试中使用这个对象,所以理想情况下我可以将 JSON 对象中的信息设置为我想要的任何内容(我不打算为 JSON 对象获取信息来自单独的文件)。我尝试了以下方法,在 JSON 对象中创建了我想要的信息的地图,然后尝试使用 gson 将其转换为 json:

val myInfo = Map(
      "info" -> Map("info1" -> "1234",
        "info2" -> "123456",
        "info3" -> "false"),
      "x" -> Map("x1_info" -> 10,
            "x2_info" -> "abcde"),
      "y" -> Map("y1_info" -> "28732",
            "y2_info" -> "defghi",
            "y3_info" -> "1261",
        "y_extra_info"-> Map("Id" -> "543890",
          "ye1" -> "asdfg",
          "ye2" -> "BOOLEAN",
          "ye3" -> false,
          "ye4" -> true,
          "ye5" -> true,
          "ye6" -> 0,
          "ye7" -> 396387
        )
      )
    )
val gson = new GsonBuilder().setPrettyPrinting.create
print(gson.toJson(myInfo))

然而,尽管它正确地生成了 JSON,但并没有在我上面的结构中生成 JSON,而是像这样构造它:

{
  "key1": "info",
  "value1": {
    "key1": "info1",
    "value1": "1234",
    "key2": "info2",
    "value2": "123456",
...(etc)...

我找到了一种不优雅的方法来实现我想要的,方法是创建一个包含我期望的 JSON 的字符串,然后解析为 JSON(但我认为有更好的方法)

val jsonString = "{\"info\":{\"info1\":\"1234\", \"info2\":\"123456\", " +
      "\"info3\":false}," +
      "\"x\":[{ \"x1_info\":10,\"x2_info\":\"abcde\"}]," +
      "\"y\":[{\"y1_info\":\"28732\",\"y2_info\":\"defghi\",\"y3_info\":\"1261\", " +
      "\"y_extra_info\":[{" +
      "\"Id\":\"543890\",\"ye1\":\"asdfg\"," +
      "\"ye2\":\"BOOLEAN\",\"ye3\":false,\"ye4\":true," +
      "\"ye5\":true,\"ye6\":0,\"ye7\":396387}]}]}"

我对 Scala 比较陌生,所以也许使用 Map 或将其全部写成字符串并不是最好或最“Scala 方式”?

有没有一种简单的方法可以使用 gson 或 spray 或其他方式创建这样的 JSON 对象?

一般来说,没有充分的理由将 GSON 与 Scala 一起使用,因为 GSON Java-based 并且并不真正知道如何处理 Scala 集合。在这种情况下,它不知道如何处理 Scala Map 的 key-value-ness 而是(很可能是由于反射)只是泄露了默认 Scala Map 的实现细节为小于 4 的情况定制。

JSON Scala 原生的库(例如 circe、play-json、spray-json 等)做你期望的 String-keyed Map秒。他们还 built-in 支持在 Scala 中直接处理 case classes,例如对于

case class Foo(id: String, code: Int, notes: String)

val foo = Foo("fooId", 42, "this is a very important foo!")

将序列化为类似的东西(忽略 pretty-printing 和字段排序可能存在的差异)

{ "id": "fooId", "code": 42, "notes": "this is a very important foo!" }

如果有必须使用 GSON 的硬性项目要求,我相信它确实理解 Java 的集合,因此您可以通过以下方式将 Scala Map 转换为 java.util.Map使用 CollectionConverters 中的转换(在 2.13 中,它在 scala.jdk 包中;在早期版本中,它应该在 scala.collection 中)。我不打算对此进行详细说明,因为我非常强烈的意见是,在 Scala 代码库中,最好使用 native-to-Scala JSON 库。