Skip to content

Instantly share code, notes, and snippets.

@sadache
Last active August 29, 2015 14:02
Show Gist options
  • Save sadache/d357ced8f6c942bca81a to your computer and use it in GitHub Desktop.
Save sadache/d357ced8f6c942bca81a to your computer and use it in GitHub Desktop.
Faster with much less memory consumption JSON object reader
def objectReader[T1,T2,T3,T4,R](t1: String, t2: String, t3: String, t4: String)(f: (T1,T2,T3,T4) => R)(implicit readsT1:Reads[T1], readsT2:Reads[T2], readsT3:Reads[T3], readsT4:Reads[T4]): Reads[R] = {
def orElse[A](a:A, default: =>A) = if(a!=null) a else default
Reads[R]{
case JsObject(fields) =>
var t1V:JsResult[T1] = null.asInstanceOf[JsResult[T1]]
var t2V:JsResult[T2] = null.asInstanceOf[JsResult[T2]]
var t3V:JsResult[T3] = null.asInstanceOf[JsResult[T3]]
var t4V:JsResult[T4] = null.asInstanceOf[JsResult[T4]]
var els = fields.toIterator
while((els.hasNext) && (t1V == null || t2V == null || t3V == null || t4V == null)){
val (key, value) = els.next()
key match {
case `t1` => t1V = readsT1.reads(value)
case `t2` => t2V = readsT2.reads(value)
case `t3` => t3V = readsT3.reads(value)
case `t4` => t4V = readsT4.reads(value)
case _ => //
}
}
(t1V, t2V, t3V, t4V) match {
case (JsSuccess(tt1, _), JsSuccess(tt2, _), JsSuccess(tt3, _), JsSuccess(tt4, _)) =>
JsSuccess(f(tt1, tt2, tt3, tt4))
case _ =>
List(
orElse(t1V, JsError(Seq((JsPath.\(t1), Seq(ValidationError("error.path.missing")))))),
orElse(t2V, JsError(Seq((JsPath.\(t2), Seq(ValidationError("error.path.missing")))))),
orElse(t3V, JsError(Seq((JsPath.\(t3), Seq(ValidationError("error.path.missing")))))),
orElse(t4V, JsError(Seq((JsPath.\(t4), Seq(ValidationError("error.path.missing"))))))
).collect { case e: JsError => e }.reduceLeft(_.++(_))
}
case js => JsError(Seq(JsPath() -> Seq(ValidationError("error.expected.jsobject"))))
}
}
@jto
Copy link

jto commented Jun 23, 2014

Good point. I'm not a big fan of the solution though, as you may have expected ;)

A definition of JsObject along the line of case class JsObject(fields: Map[String, JsValue]) would be much more appropriate in your case.

@sadache
Copy link
Author

sadache commented Jun 23, 2014

It used to be so, except you'd loose the original order of fields :)

@jto
Copy link

jto commented Jun 24, 2014

I know. There's no "good" solution :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment