Scala Experts , need your help . task is to parse this json and return list of ModelIds for store 'livingstone' which has 'organic' = true.
In this case only RT001 has organic value as true.Please help.
Note: trying to use existing liftweb library .
package Exercises
import net.liftweb.json.{DefaultFormats, _}
object test1 extends App {
val json_response =
"""{
"requestId": "91ee60d5f1b45e#316",
"error": null,
"errorMessages": [
],
"entries": [
{
"modelId":"RT001",
"sku": "SKU-ASC001",
"store": "livingstone",
"ttlInSeconds": 8000,
"metadata": {
"manufactured_date": "2019-01-22T01:25Z",
"organic": "true"
}
},
{
"modelId":"RT002",
"sku": "SKU-ASC002",
"store": "livingstone",
"ttlInSeconds": 8000,
"metadata": {
"manufactured_date": "2019-10-03T01:25Z",
"organic": "false"
}
}
] }"""
val json = parse(json_response)
implicit val formats = DefaultFormats
val elements = (json \\ "entries").children
for (subs <- elements) {
val m = subs.extract[Subs]
println(s"Subscriptions: ${m.modelId}, ${m.store}")
println(" k,v: " + m.metadata.exists(_ == ("organic", "true")))
}
case class Subs(modelId: String, store: String, metadata: Map[String, String])
}
Getting Error. Also need help how to filter based on store=living stone and organic=true .
Exception in thread "main" net.liftweb.json.MappingException: No usable value for modelId
Do not know how to convert JArray(List(JString(RT001), JString(RT002))) into class java.lang.String
Final Working code with help from experts:
val json = parse(json_response)
implicit val formats = DefaultFormats
case class Sales(modelId: String, sku: String, store: String, ttlInSeconds: Int, metadata: Map[String, String])
case class Response(entries: List[Sales])
val json1 = parse(json_response)
val response = json.extract[Response]
val subs = response.entries.filter { e =>
e.store == "livingstone" &&
e.metadata.get("organic").contains("true")
}
subs.foreach(x=>println(x.modelId))
When processing JSON it is best to convert the whole structure to Scala and then process the Scala, rather than directly processing the JSON.
So create a Response
class and extract that in a single operation, and then process the entries
field as appropriate.
Here is some completely untested code:
case class Response(entries: List[Subs])
val json = parse(json_response)
val response = json.extract[Response]
val subs = response.entries.filter{e =>
e.store == "livingstone" &&
e.metadata.get("organic").contains("true")
}
Note that this should work in any JSON library that allows you to extract a class
from JSON.