Reputation: 522
I have json which is having same structure in field repeating.
case class RuleJson(`type`: String, attribute: Int, operator: Option[String], value: String, is_value_processed: String, aggregator: String, conditions: RuleJson)
object RuleJson {
implicit val reads = Json.reads[RuleJson]
}
So the conditions key will have same RuleJson case structure. (though optional)
I am getting "No implicit Reads for models.RuleJson available." error.
My JSON is
{
"type": "salesrule/rule_condition_combine",
"attribute": null,
"operator": null,
"value": "1",
"is_value_processed": null,
"aggregator": "all",
"conditions": [
{
"type": "salesrule/rule_condition_product_subselect",
"attribute": "qty",
"operator": "==",
"value": "5",
"is_value_processed": null,
"aggregator": "all",
"conditions": [
{
"type": "salesrule/rule_condition_product",
"attribute": "quote_item_price",
"operator": "==",
"value": "200",
"is_value_processed": false
}
]
}
]
}
So if you see condition field is repeating, how do I validate such JSON in play scala 2.3?
Upvotes: 2
Views: 926
Reputation: 8901
The key here is to change your case class so it actually matches the data you want to read (e.g. make optional values Option[String]
etc) and then to use the lazyRead[T]
functions to read values using the Reads
you are currently constructing. Here's a case class (altered as appropriate) which works for your data:
case class RuleJson(
`type`: String,
attribute: Option[String],
operator: Option[String],
value: String,
isValueProcessed: Option[Boolean],
aggregator: Option[String],
conditions: Seq[RuleJson]
)
object RuleJson {
implicit val reads: Reads[RuleJson] = (
(__ \ "type").read[String] and
(__ \ "attribute").readNullable[String] and
(__ \ "operator").readNullable[String] and
(__ \ "value").read[String] and
(__ \ "is_value_processed").readNullable[Boolean] and
(__ \ "aggregator").readNullable[String] and
(__ \ "conditions").lazyReadNullable[Seq[RuleJson]](Reads.seq(RuleJson.reads))
.map(opt => opt.toSeq.flatten)
)(RuleJson.apply _)
}
Two things to notice here:
conditions
is defined as a Seq[RuleJson]
, but since it might not exist at all in the source JSON it's read as an optional value and the empty case mapped to an empty sequencelazyReadNullable
for the list of conditions and pass it an explicit reference to the Reads
we are currently constructing. If we were not to use the lazy...
variant the reads might crash with a null pointer error, since it makes a reference to something not yet defined (the lazy
variants basically use Scala call-by-name parameters which aren't evaluated until they're needed.)Upvotes: 1