Question: Please correct me if I am wrong, but when using Java with say Spring MVC you didn't have to create these extra classes to map your Java class to JSON and JSON to class.

Why do you have to do this in Play with Scala? Is it something to do with Scala?

```
case class Location(lat: Double, long: Double)

implicit val locationWrites: Writes[Location] = (
  (JsPath \ "lat").write[Double] and
  (JsPath \ "long").write[Double]
)(unlift(Location.unapply))

implicit val locationReads: Reads[Location] = (
  (JsPath \ "lat").read[Double] and
  (JsPath \ "long").read[Double]
)(Location.apply _)

```

Answer: 
The reason why you have to do it in Play is a **framework design choice**, and it is a very good one.

In Play, the mechanism relies on **Scala implicits**, which are a very powerful feature leveraged to make the mechanism highly **pluggable** , in the sense that at the moment you call:

```
Json.toJson(Location(4.5, 5.3)) 

```

The compiler will look for an **implicit** in scope matching the required type. The **Scala language specification** describes the algorithm to resolve implicits, and such algorithm is designed in a way that you can "**import**" an implicit in a limited scope. Thanks to this feature, in different part of your program you can make visible a different implementation of your Reads / Writes or any typeclass . 

```
object MyImplicits {

    object ImplicitJson1{
        implicit val write:Write[Location] = "write to json all fields"
    }

    object ImplicitJson2{
        implicit val write:Write[Location] = "skip field a"
    }
}

object MyBusinessCode{

    def f1(location:Location){
        import MyImplicits.ImplicitJson1._
        Json.toJson(location)
    }
    def f2(location:Location){
        import MyImplicits.ImplicitJson2._
        Json.toJson(location)
    }

    def dynamicChoice(location:Location){
        implicit val write = {
            if(location.isEurope)           
                MyImplicits.ImplicitJson1.write
            else
                MyImplicits.ImplicitJson2.write
        }
        Json.toJson(location)
    }

}

```

Instead, in Spring this is typically done through introspection and reflection. You might need to use annotations to help Spring determining how to build your Json from your data model. The consequence is that you cannot change the way it is done, and therefore you have less flexibility.

Since you might not need more flexibility, many Scala libraries/framework provides you functions to generate default implementation of the typeclass you need. That extra line of code 

```
implicit val fmt = Json.format[Location]

```

is the price that you have to pay because Play json serialization relies on implicit.
You don't need to:

```
case class Location(lat: Double, long: Double)

object Location {

  implicit val fmt = Json.format[Location]

}

Json.toJson(Location(4.5, 5.3)) // returns JsValue

```

The hand-written reads/writes/formats are useful when your JSON structure doesn't match your object definition.