0

I'm trying to parse the data from GovTrack, for example, https://www.govtrack.us/api/v2/bill/74369 . But titles is in a peculiar format:

"titles": [
 [
  "short", 
  "introduced", 
  "Public Online Information Act of 2011"
 ], 
 [
  "official", 
  "introduced", 
  "To establish an advisory committee to issue nonbinding governmentwide guidelines..."
]

]

titles is an array of each title type, with fields in a particular order. I want to read this into a more standard JSON format:

{
  'short_title': "Public Online Information Act of 2011",
  'official_title': "To establish an advisory committee to issue nonbinding governmentwide guidelines..."
}

The short title or official title may or may not be there, and there could actually be several short titles.

How do I make a Reads for this? Right now I've got:

implicit val billReads: Reads[Bill] = (
  (JsPath \ "id").read[Int] and
  (JsPath \ "display_number").read[String] and
  (JsPath \ "current_status").read[String] and
  (JsPath \ "titles")(0)(2).read[String]
  )(Bill.apply _)

How do I specify "The member of the array that has a first element equal to 'official'"?

1
  • Can you be more specific about the format? Your example isn't clear. Commented Dec 3, 2014 at 2:41

1 Answer 1

1

As far as I know, there is no out of the box way to do it, but I would do it with additional custom reader, like this:

val officialReads = new Reads[String] {
  override def reads(json: JsValue): JsResult[String] = (json \ "titles") match {
    case JsArray(titles) => titles.collectFirst({
      case JsArray(values) if (values.headOption.map(v => "official".equals(v.as[String])).getOrElse(false)) =>
        JsSuccess(values.tail.tail.head.as[String])
    }).getOrElse(JsError("No official title"))
    case _ => JsError("Can't read official title")
  }
}

And your Bill reader would look like this:

  val implicitReads: Reads[Bill] = (
    (__ \ "id").read[Int] and
    (__ \ "display_number").read[String] and
    (__ \ "current_status").read[String] and
    officialReads
    )(Bill.apply _)

I've tested, this works :)

Sign up to request clarification or add additional context in comments.

Comments

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.