1

In Scala I want to create a JSON Object or JSON String where the result would be something similar to this (i.e. a relatively basic nested 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
            }
         ]
      }
   ]
}

I plan to use this object in tests so ideally I can set the information inside the JSON object to whatever I want (I don't plan on sourcing the info for the JSON object from a separate file). I tried the following where I created a Map of the information I want in my JSON object and then tried converting it to json using gson:

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

However though it produces JSON correctly does not produce the JSON in the structure I have above but instead structures it like so:

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

I have figured out an inelegant way of achieving what I want by creating a string containing the JSON I expect and then parsing as JSON (but I assume there is a better way)

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}]}]}"

I'm relatively new to Scala so perhaps using a Map or writing it all out as a string is not the best or most "Scala way"?

Is there an easy way to create such a JSON object using preferable either gson or spray or otherwise by some other means?

1 Answer 1

4

In general, there's no good reason to use GSON with Scala, as GSON is Java-based and doesn't really know how to deal with Scala collections. In this case, it doesn't know how to deal with the key-value-ness of a Scala Map and instead (most likely due to reflection) just leaks the implementation detail of the default Scala Map being customized for the cases where the size is less than 4.

JSON libraries which are native to Scala (e.g. circe, play-json, spray-json, etc.) do what you expect for String-keyed Maps. They also have built-in support for directly handling case classes in Scala, e.g. for

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

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

will serialize as something like (ignoring possible differences around pretty-printing and field ordering)

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

If there's a hard project requirement that you must use GSON, I believe it does understand Java's collections, so you could convert a Scala Map to a java.util.Map by using the conversions in CollectionConverters (in 2.13, it's in the scala.jdk package; in earlier versions, it should be in scala.collection). I'm not going to elaborate on this, because my very strong opinion is that in a Scala codebase, it's best to use a native-to-Scala JSON library.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.