Reputation: 383
I have a list of JsObject like:
[{
"a":"test1",
"b": 2,
"c": 5,
"errors": "Error example"
}]
I would like to get something like this a:List[Option[String]], b: List[Option[Int]]
and so on. I need an option since not all the fields are alway present.
My code is:
jsObjList.map(js => {
val a = (js \ "a").asOpt[String]
val b = (js \ "b").asOpt[Int]
val c = (js \ "c").asOpt[Int]
val er= (js \ "errors").asOpt[String]
(a, b, er)
})
I read about unzip
and unzip3
but I haven't found a generic function.
P.S. I am using Scala Play for the json parsing
Thanks for your help!
Upvotes: 0
Views: 474
Reputation: 14825
Class to extract values from raw JSON.
case class Foo(a: Option[String], b: Option[Int], c: Option[Int],errors: Option[String])
object Foo {
// Automatically generate json reader and writer for the class Foo
implicit val format = Json.format[Foo]
}
Keeping the implicit value in companion object of Foo will make the Scala to pick up the implicit when required automatically.
Code to parse JSON into list of case class instances
payload.validate[List[Foo]]
Use validateOpt
in case you expect any parse error
payload.validateOpt[List[Foo]]
scala> :paste
// Entering paste mode (ctrl-D to finish)
val str = """
[{
"a":"test1",
"b": 2,
"c": 5,
"errors": "Error example"
}]
"""
// Exiting paste mode, now interpreting.
str: String =
"
[{
"a":"test1",
"b": 2,
"c": 5,
"errors": "Error example"
}]
"
scala> val payload = Json.parse(str)
payload: play.api.libs.json.JsValue = [{"a":"test1","b":2,"c":5,"errors":"Error example"}]
scala> case class Foo(a: Option[String], b: Option[Int], c: Option[Int],errors: Option[String])
defined class Foo
scala> implicit val format = Json.format[Foo]
format: play.api.libs.json.OFormat[Foo] = play.api.libs.json.OFormat$$anon$1@53a0b0a3
scala> payload.validate[List[Foo]]
res5: play.api.libs.json.JsResult[List[Foo]] = JsSuccess(List(Foo(Some(test1),Some(2),Some(5),Some(Error example))),)
Upvotes: 1
Reputation: 3474
You can parse JSON as a Scala case class with a companion object containing a special val called implicit val format = Json.format[*your class*]
.
Here's an example similar to yours:
import play.api.libs.json.Json
val body =
"""{
| "a":"my string",
| "b": 1,
| "c": 2
|}
""".stripMargin
val body2 =
"""{
| "a":"my string",
| "c": 5
|}
""".stripMargin
case class MyClass(a: Option[String], b: Option[Int], c: Option[Int])
object MyClass {
implicit val format = Json.format[MyClass]
}
Using this, calling Json.parse(body).as[MyClass]
gives:
res0: MyClass = MyClass(Some(my string),Some(2),Some(5))
Calling this Json.parse
function with missing fields (assuming they are optional), such as Json.parse(body2).as[MyClass]
gives:
res1: MyClass = MyClass(Some(my string),None,Some(5))
If one of the missing fields is not Optional, this parse will not work.
Upvotes: 0