0

Given a json:

val json = """
{
  "persons": [
    {"name": "Foo", "age": 21},    
    {"name": "Bar", "age": 22},
    {"name": "Baz", "age": 23}
  ]
}
"""

How to construct a play Reads[List[String]] which will extract list of names form that json?

import play.api.libs.json._

val reads: Reads[List[String]] = ???

val names: List[String] = reads.reads(Json.parse(json)) 
// expecting List("Foo", "Bar", "Baz")

2 Answers 2

3

Could try the workaround?


final case class Person(name: String, age: Int)
object Person {
  implicit val PersonFormat = Json.format[Person]
}


val jsonStr= """
{
  "persons": [
    {"name": "Foo", "age": 21},
    {"name": "Bar", "age": 22},
    {"name": "Baz", "age": 23}
  ]
}
"""

(Json.parse(jsonStr) \ "persons").as[List[Person]].map(p => p.name)



Or

((Json.parse(jsonStr) \ "persons") \\ "name").map(_.as[String])
Sign up to request clarification or add additional context in comments.

3 Comments

If for easy: ((Json.parse(jsonStr) \ "persons") \\ "name").map(_.as[String]) . that is ok
The goal is to define a Reads, not a JsResult + .as[T] is unsafe
This is a good approach it worked fine to me.
1

Just compose with Reads.

import play.api.libs.json._

val input = Json.parse("""
{
  "persons": [
    {"name": "Foo", "age": 21},    
    {"name": "Bar", "age": 22},
    {"name": "Baz", "age": 23}
  ]
}
""")

val nameReads = (JsPath \ "name").read[String]
val listReads: Reads[Seq[String]] = Reads.seq(nameReads)

(input \ "persons").validate(listReads)
// JsSuccess(Vector(Foo, Bar, Baz),)

1 Comment

Actually the question was How to construct a play Reads[List[String]]. My edit to your response provided this information, shame that you have rejected it...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.