I need help to create a json format from a case class

Dear community ,
I tried to create a json file from case classes but I am struggling on how to obtain the correct json format.

This is what I’d like to obtain (a list of landmark points with an Id and the coordinates of each landmark).

[
{
“id”: “L0”,
“coordinates”: [
-39.55951690673828,
26.436471939086914,
-207.72596740722656
]
},
{
“id”: “L1”,
“coordinates”: [
-8.773856163024902,
41.83223342895508,
-144.54759216308594
]
},
{
“id”: “L2”,
“coordinates”: [
18.707429885864258,
45.386436462402344,
-202.30406188964844
]
},
etc.

So far, I managed to convert a single landmark to json as the codes below:

I used spray-json and I have those two case classes:

case class Landmarks(values : Seq[Landmark])
case class Landmark(id: String, point: Point[_3D])

object MyJsonProtocol extends DefaultJsonProtocol {
implicit object myLMJsonFormat extends RootJsonFormat[Landmark[_3D]] {

  def write(l: Landmark[_3D]) = JsObject(
    "id" -> JsString(l.id),
    "coordinates" -> arrayFormat[Double].write(l.point.toArray)
  )

  def read(value: JsValue) = ???
}}

I call this object by:

import MyJsonProtocol._

val LM3: Landmark[_3D] = new Landmark[_3D](“LM0”, Point(-8.77, 41.83, -144.54))
val LM4: Landmark[_3D] = new Landmark[_3D](“LM1”, Point(5.0, 4.0, -1.1))
val json3 = myLMJsonFormat.write(LM3)
val json33 = myLMJsonFormat.write(LM4)

println(“JSON string read:”)
val json4 = json3.prettyPrint
println(json4)

val json44 = json33.prettyPrint
println(json44)

I get those results:

{
“coordinates”: [-8.77, 41.83, -144.54],
“id”: “LM0”
}
{
“coordinates”: [5.0, 4.0, -1.1],
“id”: “LM1”
}

Could someone help me how to get the whole list from a sequence of landmarks ? I think I’m not so far from the solution (I am new to Scala) …

Thank you very much

Hello,
So you have several Landmark objects and want them to be in a JSON list, right?

The first step would be to put them into a Scala collection, e.g. List or Seq, like so:

val all = List(LM3, LM4)

I think you tried something similar with the Landmarks case class, but an additional class isn’t necessary. The spray library provides a toJson method for any Scala object for which it knows how to represent it in JSON, so you can convert them directly to a json list:

val jsonList = all.toJson
val jsonStr = jsonList.prettyPrint

This would replace the calls to myLMJsonFormat.write. To know how the list and its elements have to be represented, toJson uses implicit JsonFormat objects defined with the right type parameter (in your case myLMJsonFormat). This kind of usage of implicits is called type classes. Here, JsonFormat is the type class, and myLMJsonFormat is an instance of that type class for Landmark[_3D].

The result of jsonList.prettyPrint:

[{
  "coordinates": [-8.77, 41.83, -144.54],
  "id": "LM0"
}, {
  "coordinates": [5.0, 4.0, -1.1],
  "id": "LM1"
}]

(NB: I changed your case classes a bit for testing this, as you left out the definition of _3D, but I don’t think any of the json code is affected by that)

2 Likes

A BIG thank you, it is working (I’m new to Scala and json :wink: I was struggling for a couple of days !))