Soy nuevo en jugar framework e intento integrar un microservicio. Estoy usando WSClient para llamar a un servicio web. Para llamar a una API de reposo POST, estoy pasando el cuerpo de la solicitud que contiene algunos parámetros obligatorios y algunos opcionales. Mi pregunta es ¿cómo pasar parámetros opcionales aquí?

Mi muestra de código es

def add = Action.async { implicit request =>
    UserDataForm.bindFromRequest.fold(
      profileForm => {
        val response = profileForm.errorsAsJson
        Future(BadRequest(response).as("application/json"))
      },
      userData => try {
        ws.url("http://localhost:9000/" + "api/profile")
          .post(
            Map("userId" -> userData.userId, "firstName" -> userData.firstName, "lastName" -> userData.lastName, "country" -> userData.country, "address" -> userData.address)).map { response =>

          OutputWithErrors(response.body, response.status)
        }
      } catch {
        case e: Exception =>
          Future(BadRequest(Message(false, e.getMessage).toJson.prettyPrint).as("application/json"))
      })
  }

Así que aquí address es un parámetro opcional.

Y datos de formulario, es decir, userData aquí

case class UserForm(userId: String, firstName: String, lastName: String, country: String, address: Option[String])
  val UserDataForm = Form(
    mapping(
      "userId" -> nonEmptyText,
      "firstName" -> nonEmptyText,
      "lastName" -> nonEmptyText,
      "country" -> nonEmptyText,
      "address" -> optional(text)
    )(UserForm.apply)(UserForm.unapply)
  )

Entonces, mientras llama a la API del servicio de descanso cerca de ws.url(...)post(Map("userId" -> userData, ...)), el compilador se queja de No implicits found for parameter evidence$2: BodyWritable[Map[String, Serializable]]

0
Shashi Shekhar 10 oct. 2019 a las 13:39

1 respuesta

La mejor respuesta

El problema aquí es el Map que le está pasando a post. Todas las entradas menos una son (String, String), pero la última es (String, Option[String]).

El compilador ahora tiene que averiguar cuál podría ser el tipo de esta colección y sube en la jerarquía de tipos. El mejor tipo que puede encontrar es Map[String, Serializable]. Porque ese es el implemento de opción y cadena de súper tipo más estrecho.

Esta es la definición de publicación:

def post[T: BodyWritable](body: T): Future[Response]

Puede ver que hay una restricción de tipo en T, lo que significa que necesita un convertidor implícito * para el cuerpo que se pasa para publicar en BodyWritable. Puede encontrar BodyWritables implícitos en DefaultBodyWritables. Y no hay BodyWritable[Map[String, Serializable]]. Pero hay uno para Map[String, String]

Tienes que elegir:

  1. Cambie el mapa para que tenga el tipo Map[String, String], ya sea proporcionando un valor predeterminado para address a través de getOrElse o no agregue la dirección al mapa si es Ninguno.
  2. Escriba un BodyWritable para Map [String, Serializable]. (Lo que podría no ser posible de una manera satisfactoria)

Te sugiero que vayas con el n. ° 1.

* Por favor corríjame si ese no es el término correcto para este tipo de implicaciones.

1
Saskia 11 oct. 2019 a las 10:23