2

I am trying to make somethink like that:

case class Obj(name: String, list: List[Integer], isPossible: Boolean) {    
  override def apply(name: String, list: List[Integer]): Obj = {
    Obj(name, list, list.exists((x: Integer) => x >= 10 && x <= 100))
  }
}

implicit val objReads: Reads[Obj] = (
(__ \ "name").read[String] and
(__ \ "list").read[List[Integer]]
)(Book.apply _)

but it doesn't compile, it returns me a error:

Overloaded method value [apply] cannot be applied to  ((String, List[Integer], Boolean) => models.Api.Obj)

is it possible to do this, or just i have to have the same amount of fields in case class and in read combinator, and this is not possible

1 Answer 1

2

There are a few problems here. First, the apply method for a case class is defined within it's companion object, not the case class itself. The second problem is that once you define the apply method within the companion object, it's going to cause an ambiguous reference error in Obj.apply _. This is because your declaration of apply is an overload, and not an override, since the signatures do not match.

One way to solve this would be to remove isPossible from the constructor of Obj, and instead make it a method or val. You would still be able to access it the same way.

case class Obj(name: String, list: List[Int]) {
    val isPossible: Boolean = list.exists((x: Int) => x >= 10 && x <= 100)
}

object Obj {
    implicit val objReads: Reads[Obj] = (
        (__ \ "name").read[String] and
        (__ \ "list").read[List[Int]]
    )(Obj.apply _)
}

The only problem this poses is that isPossible would no longer be included in JSON writes, which can be fixed like so:

implicit val objWrites: Writes[Obj] = (
    (__ \ "name").write[String] and
    (__ \ "list").write[List[Int]] and 
    (__ \ "isPossible").write[Boolean]
)( obj => (obj.name, obj.list, obj.isPossible) )

Alternatively, you could rename the overloaded apply to something else, and use that for Reads instead of Obj.apply. However, I think keeping isPossible as a val is better, because it's calculation would be done on object creation, and not when being passed to the constructor. This would ensure that you could not just call Obj("test", List(1), true) with an invalid state for isPossible.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this helps a lot. That was a lesson for me ))
great suggestion with creating a method specifically for reading (fx. json).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.