Search code examples
scalaspray-json

Why does spray-json apply this hierarchy way in RootJsonFormat?


Recently, I am reading the source code of Spray-json. I noted that the following hierarchy relation in JsonFormat.scala, please see below code snippet

/**
* A special JsonFormat signaling that the format produces a legal JSON root 
*  object, i.e. either a JSON array
* or a JSON object.
*/
trait RootJsonFormat[T] extends JsonFormat[T] with RootJsonReader[T] with RootJsonWriter[T]

To express the confusion more convenient, I draw the following diagram of hierarchy:

enter image description here

According to my limited knowledge of Scala, I think the JsonFormat[T] with should be removed from the above code. Then I cloned the repository of Spary-json, and comment the code JsonFormat[T] with

trait RootJsonFormat[T] extends RootJsonReader[T] with RootJsonWriter[T]

Then I compile it in SBT(use package/compile command) and it passed to the compiling process and generates a spray-json_2.11-1.3.4.jar successfully.

enter image description here

However, when I run the test cases via test command of SBT, it failed.

enter image description here

So I would like to know why. Thanks in advance.


Solution

  • I suggest you to not think of it in terms of OOP. Think of it in terms of type classes. In case when some entity must be serialized and deserialized at the same time, there is a type class JsonFormat that includes both JsonWriter and JsonReader. This is convenient since you don't need to search for 2 type class instances when you need both capabilities. But in order for this approach to work, there has to be an instance of JsonFormat type class. This is why you can't just throw it away from hierarchy. For instance:

    def myMethod[T](t: T)(implicit format: JsonFormat[T]): Unit = { 
      format.read(format.write(t))
    }
    

    If you want this method to work properly there has to be a direct descendant of JsonFormat and a concrete implicit instance of it for a specific type T.

    UPD: By creating an instance of the JsonFormat type class, you get instances for JsonWriter and JsonReader type classes automatically (in case when you need both). So this is also a way to reduce boilerplate.