Another, perhaps simpler, solution would be to do a map, for example:
case class GoogleDoc(id: String, etag: String, created: LocalDateTime)
object GoogleDoc {
import org.joda.time.LocalDateTime
import org.joda.time.format.ISODateTimeFormat
implicit val googleDocReads: Reads[GoogleDoc] = (
(__ \ "id").read[String] ~
(__ \ "etag").read[String] ~
(__ \ "createdDate").read[String].map[LocalDateTime](x => LocalDateTime.parse(x, ISODateTimeFormat.basicdDateTime()))
)(GoogleDoc)
}
UPDATE
If you had a recurring need for this conversion, then you could create your own implicit conversion, it is only a couple of lines of code:
import org.joda.time.LocalDateTime
import org.joda.time.format.ISODateTimeFormat
implicit val readsJodaLocalDateTime = Reads[LocalDateTime](js =>
js.validate[String].map[LocalDateTime](dtString =>
LocalDateTime.parse(dtString, ISODateTimeFormat.basicDateTime())
)
)