Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a JSON object in Scala?

Tags:

json

scala

First of all, I've searched a lot at Google and StackOverflow for questions like that, but I didn't found any useful answers (to my big surprise).

I saw something about Play Framework, how to create JSON array in Java and how to create JSON objects in Java, but I don't want to use Play Framework and I don't know if the creation of JSON objects differ from Scala to Java.

Following is the JSON I want to create. Later I'll convert the object into a string to send it via a POST request (through an API call).

{
    "start_relative": {
        "value": "5",
        "unit": "years"
    },
    "metrics": [
        {
        "name": "DP_391366" # S-Temperature - Celsius
        },
        {
            "name": "DP_812682" # Sensor-A4 Luminosity
        }
    ]
}

How can I do something like that in Scala?

like image 870
Paladini Avatar asked Oct 23 '15 16:10

Paladini


1 Answers

You should use a library that handles serialization/deserialization. I would consider choosing between Spray Json and Play Json.

I will explain to you how the process works with Play first, and it's very similar to that in Spray.

Let's say you have a class, and an object with an instance and a json as string:

case class MyClass(id: Int,
                   name: String,
                   description: String)

object Data {
  val obj: MyClass = MyClass(1, "me", "awesome")
  val str: String =
      """
        |{
        | "id": 1,
        | "name": "me",
        | "description": "awesome"
        |}
      """.stripMargin
}

For MyClass to be serialized/deserialized, you will need an implicit formatter, specific for this, so you will create an object that contains this formatter using Play.

trait MyClassPlayProtocol {
  implicit val formatAbility = Json.format[Ability]
}
object MyClassPlayProtocol extends MyClassPlayProtocol

The serialization/deserialization will look something like this:

object PlayData {

  import play.api.libs.json.JsValue
  import play.api.libs.json.Json
  import MyClassPlayProtocol._
  import General._

  val str2Json: JsValue = Json.parse(str)
  val obj2Json: JsValue = Json.toJson(obj)

  val json2Str: String = Json.stringify(str2Json)
  val json2Obj: MyClass = obj2Json.as[MyClass]
}

In Spray, the protocol will look like this:

trait MyClassSprayProtocol extends DefaultJsonProtocol {
  implicit val myClassFormat = jsonFormat3(MyClass)
}
object MyClassSprayProtocol extends MyClassSprayProtocol

and the serialization/deserialization:

object SprayData {

  import spray.json._
  import MyClassSprayProtocol._
  import General._

  val str2Json: JsValue = str.parseJson
  val obj2Json: JsValue = obj.toJson

  val json2Str: String = str2Json.compactPrint
  val json2Obj: MyClass = obj2Json.convertTo[MyClass]
}

As you can see, it's mostly a matter of choice between this two. Both are still improved and probably will be in the near future.

Depending on the benchmark, you will find that one is better than the other by a few miliseconds (usually Spray).

I for one am using Spray at work and Play in some personal projects, and I can't say I found something fundamentally different from one to another.

EDIT:

And to finally answer your question, to go from MyClass to String (serialization), you will do something like this:

PLAY:  Json.stringify(Json.toJson(myClass))
SPRAY: myClass.toJson.compactPrint

And the deserialization:

PLAY:  Json.parse(string).as[MyClass]
SPRAY: myClass.parseJson.convertTo[MyClass]
like image 112
tasegula Avatar answered Oct 05 '22 04:10

tasegula