3

I'm having some trouble figuring out why compiler complains about not finding an implicit parameter for reads because I'm almost sure that it is in the scope. The error is the following:

Error:(13, 18) No Json deserializer found for type Config. Try to implement an implicit Reads or Format for this type. test.validate[Config].map { ^

Error:(13, 18) not enough arguments for method validate: (implicit rds: play.api.libs.json.Reads[Config])play.api.libs.json.JsResult[wings.m2m.conf.model.Config]. Unspecified value parameter rds. test.validate[Config].map { ^

and it happens in the following code:

import play.api.libs.json._
import play.api.libs.json.Reads._
import Config.JsonImplicits._

import scala.util.Try

object Test {
  def main(args: Array[String]) {

    val test = Json.obj("action" -> Config.Action.nameAcquisitionRequest.toString, "value" -> "hola")
    test.validate[Config].map {
      t => println(t)
        t
    }
  }
}

/**
 * Config companion object
 */
object Config {

  type ValueType = String

  val ActionKey = "action"

  val ValueKey = "value"

  object Action extends Enumeration {

    type Action = Value

    val nameAcquisitionRequest = Value("nameAcquisitionRequest")
    val nameAcquisitionReject = Value("nameAcquisitionReject")
    val nameAcquisitionAck = Value("nameAcquisitionAck")

    val broadcast = Value("broadcast")

  }

  /**
   * Json implicit conversions
   */
  object JsonImplicits {

    implicit object ConfigReads extends Reads[Config] {

      def hTypeCast(action: Config.Action.Value, value: Config.ValueType): Config = {
        action match {
          case Config.Action.nameAcquisitionRequest => NameAcquisitionRequest(value)
          case Config.Action.nameAcquisitionReject => NameAcquisitionReject(value)
          case Config.Action.nameAcquisitionAck => NameAcquisitionAck(value)
        }
      }

      override def reads(json: JsValue): JsResult[Config] = json match {
          case json: JsObject =>
            val action = (json \ ActionKey).as[String]
            Try(Config.Action.withName(action)) map {
              a =>
                val value = (json \ ValueKey).as[String]
                JsSuccess(hTypeCast(a, value))
            } getOrElse (JsError("Can't convert to Config"))
          case _ => JsError("Can't convert to Config")
        }
      }


    implicit object ConfigWrites extends OWrites[Config] {

      def jsObjectCreator(action: Config.Action.Value, value: Config.ValueType): JsObject = {
        Json.obj(ActionKey -> action.toString, ValueKey -> Json.toJson(value))
      }

      override def writes(o: Config): JsObject = o match {
        case c: NameAcquisitionRequest => jsObjectCreator(Config.Action.nameAcquisitionRequest, c.value)
        case c: NameAcquisitionReject => jsObjectCreator(Config.Action.nameAcquisitionReject, c.value)
        case c: NameAcquisitionAck => jsObjectCreator(Config.Action.nameAcquisitionAck, c.value)
      }
    }
  }

}

sealed trait Config {
  val value: Config.ValueType
}

/**
 * Intermediate config message
 * @param value
 */
case class NameAcquisitionRequest(override val value: String)
  extends Config

case class NameAcquisitionReject(override val value: String)
  extends Config

case class NameAcquisitionAck(override val value: String)
  extends Config

case class Broadcast(override val value: String)
  extends Config

the error occurs when executing the main method on the Test object. To make this example work, make sure to add the following dependency in the SBT: "com.typesafe.play" %% "play-json" % "2.4.1" . And I'm not sure, but maybe this resolver is needed: resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/"

1 Answer 1

0

I am not sure what you are trying to achieve and whether this solves your problem but here you go:

test.validate[Config](Config.JsonImplicits.ConfigReads).map {
  t => println(t)
    t
}
Sign up to request clarification or add additional context in comments.

2 Comments

The problem is that the "validate" function has an implicit reads parameter and if you take a look at my imports, I'm importing Config.JsonImplicits._ -> so I'm bringing an implicit reads in the scope. Your solution works perfectly, even without the type parametrization [Config], but my question is: why the compiler keeps saying that he needs an implicit reads for Config if it is already imported?
It keeps complaining even if the import statement is just at the previous line...

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.