0
votes

I have a case class as following:

case class Road(id: String, light: TrafficLight, cars: Map[String, String])

Simply, I'm trying to decode Json to List[Road].
The Json I'm trying to decode is:

[   
   {
        "id" = "A",
        "light" = "green",
        "cars": [
          {
            "Nissan" : "100"
          }
        ]
    }
]

The TrafficLight is basic enum:

object TrafficLight extends Enumeration {
    type TrafficLight = Value
    val red, yellow, green = Value
}

I've built encoder & decoder for the traffic light:

implicit val trafficLightDecoder: Decoder[TrafficLight.Value] = Decoder.enumDecoder(TrafficLight)
implicit val trafficLightEncoder: Encoder[TrafficLight.Value] = Encoder.enumEncoder(TrafficLight)

I've also built an encoder for the Map[String,String] type:

implicit val encodeMap: Encoder[Map[String, String]] = new 
Encoder[Map[String, String]] {
override def apply(values: Map[String, String]): Json = {
  values.toList
    .map(pair => Json.obj(
      (pair._1, pair._2.asJson)
    )).asJson
    }
}

And finally, encoder and decoder for the Road case class:

implicit val roadDecoder: Decoder[Road] = deriveDecoder
implicit val roadEncoder: Encoder[Road] = deriveEncoder

Now, I'm trying to parse the json to List[Road].

roadJson.as[List[Road]].toOption.getOrElse(List[Road]())

But I can't decode it - I always get an empty list, due the "else" in the getOrElse method, without any errors.
What am I doing wrong? Thanks in advance.

1

1 Answers

2
votes

When you are using .toOption.getOrElse you discard the error that may be returned when parsing your json.

If you want to see the error, you need to look at the value returned by roadJson.as[List[Road]]

My favorite choice here is to use pattern matching to look at the result:

roadJson.as[List[Road]] match {
  case Left(error) => 
    println(error) // print to debug the error
    ... // do something in case of error
  case Right(roads) => ... // do something else
}

Also the json you pasted is not valid, it uses = instead of :