-
Notifications
You must be signed in to change notification settings - Fork 0
/
JsonPattern.scala
46 lines (43 loc) · 1.49 KB
/
JsonPattern.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package util
import spray.json._
import DefaultJsonProtocol._ // !!! IMPORTANT, else `convertTo` and `toJson` won't work correctly
/**
* Created by Pahomov Dmitry on 02.04.2014.
*/
package object JsonPattern {
implicit class JsValueHelper(val jv: JsValue) {
def pattern(placeholder: JsValue) = new JsonPattern(jv, placeholder)
}
class JsonPattern(val pattern: JsValue, val placeholder: JsValue) {
private def compareStep(ax: Option[Seq[JsValue]], pattern: JsValue, source: JsValue): Option[Seq[JsValue]] = {
if (ax.nonEmpty) {
(pattern, source) match {
case (`placeholder`, s) => Some(ax.get :+ s)
case (p: JsObject, s: JsObject) if p.fields.size==s.fields.size =>
val zipped = p.fields.toSeq.zip(s.fields.toSeq)
zipped.foldLeft(ax) {
case (acc, ((kp, vp), (ks, vs))) =>
if (kp == ks && acc.nonEmpty) {
compareStep(acc, vp, vs)
} else {
None
}
}
case (p: JsArray, s: JsArray) if p.elements.size==s.elements.size =>
val zipped = p.elements.zip(s.elements)
zipped.foldLeft(ax) {
case (acc, (vp, vs)) => compareStep(acc, vp, vs)
}
case (p , s) if p==s => ax
case (_, _) => None
}
}
else {
None
}
}
def unapplySeq(source: JsValue): Option[Seq[JsValue]] = {
compareStep(Some(Seq()), pattern, source)
}
}
}