mechanikos
mechanikos

Reputation: 777

Scala Play 2 - convert JsValue to model Object

I have a Scala case class

case class SmsGatewayConfig(oracle_id: Long,sms_type: String,seconds_of_high_prio: String,allowed_operators: String,allowed_organizations: String, phone_filter: String, min_throughput:Long,max_throughput: Long,comment: String, enabled: Boolean,isGwDedicated: Boolean) and companion oject

object SmsGatewayConfig {
  implicit val smsGatewayConfig: Reads[SmsGatewayConfig] = (
    (JsPath \ "oracle-id").read[Long] and
      (JsPath \ "sms-type").read[String] and
      (JsPath \ "seconds-of-high-prio").read[String] and
      (JsPath \ "allowed-operators").read[String] and
      (JsPath \ "allowed-organizations").read[String] and
      (JsPath \ "phone-filter").read[String] and
      (JsPath \ "min-throughput").read[Long] and
      (JsPath \ "max-throughput").read[Long] and
      (JsPath \ "comment").read[String] and
      (JsPath \ "enabled").read[Boolean] and
      (JsPath \ "isGwDedicated").read[Boolean]
    )(SmsGatewayConfig.apply _)
}

and JsValue which like in string like {"oracle-id":6877851,"sms-type":["1-100"],"allowed-operators":["all"," unknown"],"phone-filter":["+7xxxxxxxxxx"],"max-throughput":1000000,"comment":"","enabled":false}

but if i try do val obj=configs.as[SmsGatewayConfig] i get too many exceptions [JsResultException: JsResultException(errors:List((/allowed-operators,List(ValidationError(error.expected.jsstring,WrappedArray()))), (/isGwDedicated,List(ValidationError(error.path.missing,WrappedArray()))), (/min-throughput,List(ValidationError(error.path.missing,WrappedArray()))), (/phone-filter,List(ValidationError(error.expected.jsstring,WrappedArray()))), (/sms-type,List(ValidationError(error.expected.jsstring,WrappedArray()))), (/allowed-organizations,List(ValidationError(error.path.missing,WrappedArray()))), (/seconds-of-high-prio,List(ValidationError(error.path.missing,WrappedArray())))))] and i have no idea what sholud i do for resolve this problem. Sorry for my bad english

Upvotes: 2

Views: 2322

Answers (1)

Adrien Aubel
Adrien Aubel

Reputation: 692

In your JSON, sms-type, allowed-operators, and phone-filter are arrays. Therefore you would need to change the following in your Reads object to:

object SmsGatewayConfig {
  implicit val smsGatewayConfig: Reads[SmsGatewayConfig] = (
    (JsPath \ "oracle-id").read[Long] and
      (JsPath \ "sms-type").read[Seq[String]] and
      (JsPath \ "seconds-of-high-prio").read[String] and
      (JsPath \ "allowed-operators").read[Seq[String]] and
      (JsPath \ "allowed-organizations").read[String] and
      (JsPath \ "phone-filter").read[Seq[String]] and
      (JsPath \ "min-throughput").read[Long] and
      (JsPath \ "max-throughput").read[Long] and
      (JsPath \ "comment").read[String] and
      (JsPath \ "enabled").read[Boolean] and
      (JsPath \ "isGwDedicated").read[Boolean]
    )(SmsGatewayConfig.apply _)
}

You also need to update your case class to represent that these fields are arrays and not just String:

case class SmsGatewayConfig(oracle_id: Long, sms_type: Seq[String], seconds_of_high_prio: String, allowed_operators: Seq[String], allowed_organizations: String, phone_filter: Seq[String], min_throughput: Long, max_throughput: Long, comment: String, enabled: Boolean, isGwDedicated: Boolean)

Additionally, it looks like some fields are missing from your JSON input: seconds-of-high-prio, allowed-organizations, min-throughput, and isGwDedicated.

To represent this in your code, use Option in your case class and readNullable in your Reads object:

case class SmsGatewayConfig(oracle_id: Long, sms_type: Seq[String], seconds_of_high_prio: Option[String], allowed_operators: Seq[String], allowed_organizations: Option[String], phone_filter: Seq[String], min_throughput: Option[Long], max_throughput: Long, comment: String, enabled: Boolean, isGwDedicated: Option[Boolean])

object SmsGatewayConfig {
  implicit val smsGatewayConfig: Reads[SmsGatewayConfig] = (
    (JsPath \ "oracle-id").read[Long] and
      (JsPath \ "sms-type").read[Seq[String]] and
      (JsPath \ "seconds-of-high-prio").readNullable[String] and
      (JsPath \ "allowed-operators").read[Seq[String]] and
      (JsPath \ "allowed-organizations").readNullable[String] and
      (JsPath \ "phone-filter").read[Seq[String]] and
      (JsPath \ "min-throughput").readNullable[Long] and
      (JsPath \ "max-throughput").read[Long] and
      (JsPath \ "comment").read[String] and
      (JsPath \ "enabled").read[Boolean] and
      (JsPath \ "isGwDedicated").readNullable[Boolean]
    )(SmsGatewayConfig.apply _)
}

All of the errors that you had, or at least most of them, should be gone with these changes.

As a small detail, I would recommend using camelCase notation instead of the underscore_based naming you used to name your case class fields.

Upvotes: 2

Related Questions