Scala Play framework 2.1 derived classes - scala

I'd like to produce JSON for a List that includes both base classes and derived classes. The code below only produces JSON for the Animal class (I do not get the breed field for the Dog type members). Some help would be appreciated.
import play.api.libs.json._
class Animal (val name:String) {
}
object Animal {
implicit object animalWrite extends Writes[Animal] {
def writes(ts: Animal) = JsObject(Seq("name" -> JsString(ts.name)))
}
}
case class Dog (override val name:String, val breed: String)
extends Animal(name) {
}
object Dog {
implicit val format = Json.format[Dog]
}
case class Cat (override val name:String, val hairLength: Int)
extends Animal(name) {
}
object Cat {
implicit val format = Json.format[Cat]
}
object helloWorld extends App {
// The list below outputs: [{"name":"Ruff","breed":"labrador"}]
// val l = List[Dog](Dog("Ruff", "labrador"))
// The list below outputs: [{"name":"Ruff"},{"name":"Fluffy"}]
// I expect to see: [{"name":"Ruff","breed":"labrador"},{"name":"Fluffy","hairLength":3}]
val l = List[Animal](Dog("Ruff", "labrador"), Cat("Fluffy", 3))
println(Json.toJson(l))
}
Scala and Play newbie here, please excuse inappropriate use of terminology.

The json API extensively uses implicit parameters which is a feature of Scala where you can provide an "implicit" parameter list and if you don't specify those parameters the compiler will try to find an object in the current scope that is marked as implicit and matches that signature.
So if you for example would write:
implicit val s = "my implicit string"
def magicPrint(implicit message: String) { println(message) }
// and then call it
magicPrint
The compiler would select s for the parameter message since it is in scope and has the correct type (String), so after the implicit resolution the last line of code would actually look more like this
magicPrint(s)
The Format/Writer is selected by the compiler, at compile time, with an implicit parameter. If you look at the signature of the method, toJson[A](item: A)(implicit writes: Writes[A]), it takes an implicit Writes[A] which in your case is a Writes[List[Animal]] since List[Animal] is the type of your list l. Play contains a default has a writer that takes care of the collection (DefaultWrites.traversableWrites) which in turn takes an implicit Writes[A] - in your case Writes[Animal], so the compiler will select and pass your animalWrites.
That your list contains different types of animals is something that happens at runtime and the compiler has no way of knowing that from the type information available at your Json.toJson(l)
So, as you see you cannot achieve what you want in the way you thought, but you can do it in almost the same way by letting the animal writer know about the subtypes, for example:
implicit object animalWrite extends Writes[Animal] {
def writes(ts: Animal) = ts match {
// this will get an implicit Writes[Dog] since d is a Dog
case d: Dog => Json.toJson(d)
// this will get an implicit Writes[Cat] since c is a Cat
case c: Cat => Json.toJson(c)
case x => throw new RuntimeException(s"Unknown animal $x")
}
}
Hope this helped!

Related

Issue when using akka-http, circe

Let's say I have this hierarchy:
sealed trait Animal {
def eat = println("eating!")
}
final case class Dog(name :String) extends Animal {override def eat= println("dog eating")}
final case class Cat(name: String) extends Animal {override def eat= println("cat eating")}
As you see I'm using akka http and circe, then I have the following:
import io.circe.syntax._
import io.circe.Json
...
pathPrefix("path" / "something") {
post {
entityAs[Map[String,Json]] { data =>
// depending on the key of the map I will create an object Dog or Animal
val transformed = data.map { d =>
d._1 match {
case "dog" => d._2.as[Dog]
case "cat" => d._2.as[Cat]
}
}
// then I will do something like
transformed.foreach(_.eat)
complete(Status.OK)
}
}
But for some reason I can't use the method eat.
And I see that the type of transformed is immutable.Iterable[Result[_ >: Dog with Cat <: Animal]] I guess that's the problem that prevent me to call eat method.
Is there anyway to fix that to be able to call the eat event?
As you noticed, the value you are getting is:
Iterable[Result[_ >: Dog with Cat <: Animal with Product]]
while:
final type Result[A] = Either[DecodingFailure, A]
In order to access the eat method, you have to do:
transformed.foreach(_.map(_.eat))
From you point of view, every time when map key is dog, its value is Dog class, but from compiler doesn't know about that.
That is why transformed is Iterable[Result[X]], and when traversing iterable you are trying to call eat method on Result type.
You have to extract value from Result object, only if it was deserialized correctly

Organizing Scala implicits associated with a type

I'd like to introduce some types to represent possible values of a field in a larger type. This fields needs to be possible to encode/decode to/from JSON and also be able to be written/read to a database.
I'm still new to Scala and the type I would like is the sum type Status = NotVerified | Correct | Wrong. Since I want to have a string representation associated with each constructor, I created a sealed case class with a String parameter and then objects extending that case class. In order to be able to encode/decode, I also need to have implicits, but I'm not sure how to structure this. I could put them in a new object inside the object, like this:
sealed case class Status(name: String)
object Status {
object NotVerified extends Status("not_verified")
object Correct extends Status("correct")
object Wrong extends Status("wrong")
object implicits {
implicit val encodeStatusJson: Encoder[Status] =
_.name.asJson
implicit val decodeStatusJson: Decoder[Status] =
Decoder.decodeString.map(Status(_))
implicit val encodeStatus: MappedEncoding[Status, String] =
MappedEncoding[Status, String](_.name)
implicit val decodeStatus: MappedEncoding[String, Status] =
MappedEncoding[String, Status](Status(_))
}
}
… and then explicitly import these where needed, but that's quite … explicit.
What is a good way of organizing such collections of a type + implicits?
The common approach is to define a sealed trait:
sealed trait Status {
def name: String
}
object Status {
case object NotVerified extends Status {
val name = "not_verified"
}
case object Correct extends Status {
val name = "correct"
}
case object Wrong extends Status {
val name = "wrong"
}
}
Or a sealed abstract class, which may look nicer in the current Scala versions:
sealed abstract class Status(val name: String)
object Status {
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
To avoid the need to import implicits, they can be placed directly in the companion object of the type. See also the question Where does Scala look for implicits? for more details, especially the section Companion Objects of a Type.
And yes, defining implicits for enumerations like that easily gets repetitive. You have to resort to reflection or macros. I recommend using the Enumeratum library, which also has integrations with Circe and Quill.
Here is an example for Circe:
import enumeratum.values._
sealed abstract class Status(val value: String) extends StringEnumEntry {
def name: String = value
}
object Status extends StringEnum[Status] with StringCirceEnum[Status] {
val values = findValues
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
And you can use it without defining any encoders/decoders explicitly or importing anything from Status:
scala> import io.circe.syntax._
scala> val status: Status = Status.Correct
status: Status = Correct
scala> status.asJson
res1: io.circe.Json = "correct"
scala> Decoder[Status].decodeJson(Json.fromString("correct"))
res2: io.circe.Decoder.Result[Status] = Right(Correct)
If you add an apply method you can create the appropriate Status from a String, which should make the Decoder work properly. And making Status abstract
sealed abstract class Status(name: String)
object Status {
object NotVerified extends Status("not_verified")
object Correct extends Status("correct")
object Wrong extends Status("wrong")
def apply(name: String): Status = name match {
case "not_verified" => NotVerified
case "correct" => Correct
case _ => Wrong
}
}
I think your existing implicits will still work, but I don't know those specific libraries...

Spray JSON: How to get implicitly declared objects into read and write methods?

I am currently struggling with spray-json writing a protocol for my data model. For deserialization of JSON data to my data transfer objects, a DAO has to be contacted to check if an appropriate object exists, otherwise a DeserializationException should be thrown.
So far, I have the following:
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object MyDtoJsonFormat extends RootJsonFormat[MyDto] {
override def write(obj: MyDto): JsValue = // Serialization implementation
override def read(json: JsValue): MyDto = {
// parse the JSON, get some parameters, let them be a, b, c
dtoLookup(a, b, c) match {
case Some(dto: MyDto) => dto
case None => throw new DeserializationException("Cannot retrieve object from DAO")
}
}
}
def dtoLookup(a: SomeType, b: SomeOtherType, c: YetAnotherType)(implicit dao: MyDAO): Option[MyDto] = {
// lookup the MyDTO with the dao instance
}
}
My test looks like the following:
class MyJsonProtocolTest extends FlatSpec with Matchers {
implicit val MyDAO = // some test instance, can be a mock object
"The protocol" should "serialize a DTO" in {
val dto: MyDTO = ...
dto.toJson.compactPrint should be("{...}")
}
}
However, the compiler complains that it cannot find the implicit MyDAO when trying to compile the MyJSONProtocol. In When testing Spray services with Scalatest, how to introduce implicit values? I asked yesterday, I was suggested to pass in the implicit parameter directly into the method, but I cannot do this here because the read method is defined in the RootJsonFormat.
When I call the dtoLookup method directly from my test code, it succeeds.
So, how do I get the MyDAO instance into my special JSON format?
One option is to make the implicit parameter a constructor parameter to one of the classes being used. This might require that you turn one of your objects into a class. Then you can make an get method on the companion object of that class that uses an implicit in scope to construct the class with the desired argument.
This doesn't really have to do with spray or scalatest, rather it's just an issue with implicits and implicit scope. Here's a simplified version:
object MyJsonProtocol {
implicit object MyDtoJsonFormat {
def read(x: Int) = dtoLookup
}
def dtoLookup(implicit x: Int) = x + 1
}
And you might consider changing that to:
class MyJsonProtocol(implicit x: Int) {
implicit object MyDtoJsonFormat {
def read(x: Int) = dtoLookup
}
def dtoLookup = x + 1
}
object MyJsonProtol {
def get(implicit x: Int) = new MyJsonProtocol
}
And then you can use this with an implicit in scope:
class MyJsonProtocolTest {
implicit val x = 5
val proto = MyJsonProtol.get
val myReadValue = proto.MyDtoJsonFormat.read //6
}
You can read about the rules for implicit scopes here, especially relevant might be the "Where do Implicits Come From" section.

Scala - Abstract types and Implicit Parameter Resolution

I'm using Scala 2.10.4.
Please bare with the analogy - the actual code is deeply embedded in a complicated program, so rather than explain that, I’ll abstract the problem in a time honoured way to talk about Animals ;-)
In scala I have 2 traits - for example:
Animal, and HouseBase.
I have no access to change Animal, but I inherit from it with classes like Dog, Rabbit, Fish. Annoyingly I can’t change every subclass as I don’t own all the subclasses I use.
My animals all live somewhere - their homes must inherit from HouseBase. I can change HouseBase and it’s subclasses (via another layer of abstraction, if I must).
So a Dog is a subclass of Animal, and would live in a Kennel which is a subclass of HouseBase.
A Rabbit would live in a Hutch, and a Fish in a Tank.
Note there is not a 1:1 relationship enforced here - a Fish could also live in a Pond, and we’d have to be able to handle that too.
What I’d hoped was that -- given a concrete animal (eg Fish), that is referenced via an abstract type Animal, and given a concrete return type (eg Tank), Scala would be able to automagically pick the correct implicit parameter in the design I have below.
object AnimalSelectionProblem extends App {
def abstractFish : Animal = new Fish(true, 20.0)
def concreteFish : Fish = new Fish(false, 30.0)
def abstractDog : Animal = new Dog("tasty bone")
def concreteDog : Dog = new Dog("yummy bone")
def abstractRabbit : Animal = new Rabbit(5)
def concreteRabbit : Rabbit = new Rabbit(10)
import HouseImplicits._
val myTank1: Tank = HouseImplicits.create(abstractFish)
val myTank2: Tank = HouseImplicits.create(concreteFish)
val myKennel1: Kennel = HouseImplicits.create(abstractDog)
val myKennel2: Kennel = HouseImplicits.create(concreteDog) // This works
val myhutch1: Hutch = HouseImplicits.create(abstractRabbit)
val myhutch2: Hutch = HouseImplicits.create(concreteRabbit) // This works
}
However there are 2 related problems.
Problem 1 - If the animal is referenced as an abstract, then the implicit parameter will only look for functions that take the abstract type (Animal) rather than the underlying concrete type. I suspect the solution may be to use ClassTags, because Scala doesn’t seem to use runtime time information? I had a go at implementing this and got hopelessly l lost (I’m fairly new to Scala!).
Problem 2 - If my animal can live in more than one type of House then a similar issue occurs, that even if a concrete return type is specified, the compiler will find the 2 implicit objects for Fish ambiguous. I’m a bit stumped about what to do here!
I can dream up solutions with manual boilerplate to match the type at runtime, but this isn’t very extensible.
Any ideas gratefully received! Rest of the code is below.
Edit - these links seems to confirm what I had suspected. That compile time polymorphism is used and hence the runtime type cannot be known:
http://like-a-boss.net/2013/03/29/polymorphism-and-typeclasses-in-scala.html
https://softwareengineering.stackexchange.com/questions/258698/is-it-possible-to-have-ad-hoc-polymorphism-with-runtime-dispatch
So, I guess my question now is, given this, is there a way to modify my example to use runtime dispatch?
Animals:
trait Animal {
}
class Dog(val boneName: String) extends Animal
class Rabbit(val length: Int) extends Animal
class Fish(val likesFrogs: Boolean, val optimumTemp: Double) extends Animal
Houses and Implicits:
sealed trait HouseBase
// Made up some arbitrary member variables
case class Kennel(posessions: Seq[String]) extends HouseBase
case class Hutch(length: Int) extends HouseBase
case class Tank(waterTemp: Double) extends HouseBase
case class Pond(containsFrog: Boolean) extends HouseBase
sealed trait HouseCreator[A <: Animal, HB <: HouseBase] {
def create(animal: A): HB
}
object HouseImplicits {
implicit object BuildKennelForDog extends HouseCreator[Dog, Kennel] {
override def create(dog: Dog): Kennel = {
new Kennel(Seq(dog.boneName))
}
}
implicit object BuildTankForFish extends HouseCreator[Fish, Tank] {
override def create(fish: Fish): Tank = {
new Tank(fish.optimumTemp)
}
}
implicit object BuildPondForFish extends HouseCreator[Fish, Pond] {
override def create(fish: Fish): Pond = {
new Pond(fish.likesFrogs)
}
}
implicit object BuildHutchForRabbit extends HouseCreator[Rabbit, Hutch] {
override def create(rabbit: Rabbit): Hutch = {
new Hutch(rabbit.length*5)
}
}
def create[A <: Animal, H <: HouseBase](animal: A)(implicit house: HouseCreator[A,H]) : H = {
val newHouse = house.create(animal)
newHouse
}
}
So basically you want the following design:
At compile time the concrete type of HouseBase is known.
At compile time the concrete type of Animal is not known.
Create a specific type HouseBase for Animal provided runtime animal data.
Can't change Animal implementations, and don't really want to change HouseBase implementations.
The desirable thing is of course to have the concrete types of Animals available at compile time. Since there seems to be some knowledge of that (you know which HouseBase to create for an animal variable at compile time), you may try to use type-safe cast from shapeless to get an Option of a concrete Animal type.
But if it's not possible you have to use run-time dispatch of animals.
In that case I think the method create should have the following signature:
def create[HB <: HouseBase](animal: Animal): Option[HB]
You know the concrete type of the HouseBase so you may as well pass it as type parameter, and the return value is Option to account for a possible mismatch between the type of the provided animal and suitable animal types for a concrete HouseBase
One possible way to implement that is the following code with a single object that has all the knowledge about the production of HouseBases from Animals (it should be also possible to achieve the same thing by moving the creation code into companion objects of concrete HouseBases):
sealed trait HouseCreator[HB <: HouseBase] {
def create(animal: Animal): Option[HB]
}
object HouseCreator {
implicit object KennelCreator extends HouseCreator[Kennel] {
def create(animal: Animal): Option[Kennel] = animal match {
case dog: Dog => Some(Kennel(Seq(dog.boneName)))
case _ => None
}
}
implicit object HutchCreator extends HouseCreator[Hutch] {
def create(animal: Animal): Option[Hutch] = animal match {
case rabbit: Rabbit => Some(Hutch(rabbit.length * 5))
case _ => None
}
}
implicit object TankCreator extends HouseCreator[Tank] {
def create(animal: Animal): Option[Tank] = animal match {
case fish: Fish => Some(Tank(fish.optimumTemp))
case _ => None
}
}
implicit object PondCreator extends HouseCreator[Pond] {
def create(animal: Animal): Option[Pond] = animal match {
case fish: Fish => Some(Pond(fish.likesFrogs))
case _ => None
}
}
def create[HB <: HouseBase : HouseCreator](animal: Animal): Option[HB] =
implicitly[HouseCreator[HB]].create(animal)
}
Then you can call the functions this way:
val myTank1: Option[Tank] = HouseCreator.create[Tank](abstractFish)
val myTank2: Option[Tank] = HouseCreator.create[Tank](concreteFish)
// Types of the variables can also be inferred automatically
val myKennel1 = HouseCreator.create[Kennel](abstractDog)
val myKennel2 = HouseCreator.create[Kennel](concreteDog)
val myhutch1 = HouseCreator.create[Hutch](abstractRabbit)
val myhutch2 = HouseCreator.create[Hutch](concreteRabbit)
Also, the boilerplate code in HouseCreator can be reduced by using PartialFunctions:
sealed trait HouseCreator[HB <: HouseBase] {
def create: PartialFunction[Animal, HB]
}
object HouseCreator {
implicit object KennelCreator extends HouseCreator[Kennel] {
def create = {
case dog: Dog => Kennel(Seq(dog.boneName))
}
}
implicit object HutchCreator extends HouseCreator[Hutch] {
def create = {
case rabbit: Rabbit => Hutch(rabbit.length * 5)
}
}
implicit object TankCreator extends HouseCreator[Tank] {
def create = {
case fish: Fish => Tank(fish.optimumTemp)
}
}
implicit object PondCreator extends HouseCreator[Pond] {
def create = {
case fish: Fish => Pond(fish.likesFrogs)
}
}
def create[HB <: HouseBase : HouseCreator](animal: Animal): Option[HB] =
implicitly[HouseCreator[HB]].create.lift(animal)
}
What you want is for the compiler to deduce the run-time type of your subclass when it is declared statically as an instance of its superclass. This is provably impossible, so don't try to make it work unless you're hoping to win some kind of computer science award!
Instead of parameterizing your HouseCreator class, you could write it to have a single create() method that accepts an object of type Animal. It could create the appropriate House using a case match that matches based on the run-time subtype of Animal.
sealed trait HouseCreator {
def create(animal: Animal): HouseBase {
animal match {
case dog: Dog => new Kennel(Seq(dog.boneName))
case fish: Fish => // etc...
}
}
}
This would only be able to return a HouseBase object rather than a specific subclass (at least as I implemented it here). You could always case match the return value as well.

Is it better to use vals or object when providing instances of a typeclass in Scala

The type class pattern in Scala involves defining a trait such as:
trait Show[T] {
def show(obj: T): String
}
Then you can define instantiations of this type class as such:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
The advantage of defining these instantiations for basic types in the companion object is that they are automatically in scope whenever the type class is concerned (roughly).
Functionally it would appear defining the instantiation as an implicit val or an implicit object does not change much.
Is there a difference? Is one way better than the other?
There is actually more than the type names between val and object.
You know, object in Scala is something like a singleton in Java.
Maybe you thought that both string and BooleanShow are in an object not a class so they have no difference, but that's not true.
They are val and object no matter what.
Try this in Scala REPL.
trait Show[T] {
def show(obj: T): String
}
object Show {
println("!! Show created")
implicit val string = new Show[String] {
println("!! string created")
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
println("!!BooleanShow created")
def show(obj: Boolean): String = obj.toString
}
}
If only the definition is done, then no printlns are executed afterwards, since Show is a singleton in effect. It's not created yet.
Next, execute Show in Scala REPL.
scala> Show
!! Show created
!! string created
res0: Show.type = Show$#35afff3b
You see, printlns in Show and Show.string were called, but the one in Show.BooleanShow was not.
You can execute Show.BooleanShow next in Scala REPL.
scala> Show.BooleanShow
!!BooleanShow created
res1: Show.BooleanShow.type = Show$BooleanShow$#18e419c5
Show.BooleanShow was initialized at last. It is a singleton, so it is lazy.
Basically, your question is the same as val and object inside a scala class? except that your val and object are defined in an object, but the linked question tries to find differences val and object defined in a class and the method in val uses reflection (but yours uses overriding, so no reflection is involved). implicit basically does not make difference in what they are.
I think you already know the difference between class and object. Further information can be found in the linked question.
Since they say always to use explicit types for implicits, prefer val over object.
Compare Why can't Scala find my typeclass instance defined implicitly in the companion object, when the typeclass is not in a dedicated source file? where it makes a difference.
Make it lazy if necessary.
Elaboration:
scala> trait T
defined trait T
scala> object X { implicitly[T] ; object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; object O extends T }
^
scala> object X { implicitly[T] ; implicit object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T }
^
scala> object X { implicitly[O.type] ; implicit object O extends T }
defined object X
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
^
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y: T = O }
defined object X
The inferred type of O is the singleton type O.type.
With val x = new X { } you are creating an anonymous subclass of X, whereas with object x extends X you create a "proper" subclass. I would think that the overhead of an object is minimal, and as #applicius points out, it has proper name. Therefore I suggest to go for the object in this case.