Skip to content

Commit

Permalink
Yet more safe and efficient removing of keys without an internal `toS…
Browse files Browse the repository at this point in the history
…et` call that isn't safe: scala/bug#11203
  • Loading branch information
plokhotnyuk committed Aug 17, 2019
1 parent bd4471c commit e4c8b61
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
19 changes: 12 additions & 7 deletions src/main/scala/com/github/pathikrit/dijon/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,27 @@ package object dijon {

def ++(that: SomeJson): SomeJson = (this.underlying, that.underlying) match {
case (a: JsonObject, b: JsonObject) =>
val res = a.clone()
b.keys foreach {
case key if res contains key => res(key) = res(key) ++ b(key)
case key => res(key) = b(key)
val res = new util.LinkedHashMap[String, SomeJson](a.size + b.size)
a.foreach { case (k, v) =>
res.put(k, if (b.contains(k)) v ++ b(k) else v.deepCopy)
}
res
b.foreach { case (k, v) =>
if (!res.containsKey(k)) res.put(k, v.deepCopy)
}
res.asScala
case _ => that.deepCopy
}

def --(keys: String*): SomeJson = underlying match {
case obj: JsonObject => obj -- keys
case obj: JsonObject =>
val res = obj.clone()
keys.foreach(res -= _)
res.deepCopy
case _ => deepCopy
}

def remove(keys: String*): Unit = underlying match {
case obj: JsonObject => obj --= keys
case obj: JsonObject => keys.foreach(obj -= _)
case _ => ()
}

Expand Down
11 changes: 10 additions & 1 deletion src/test/scala/com/github/pathikrit/dijon/DijonSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ class DijonSpec extends FunSuite {
assert(t.b.c.a == None)
}

test("handle merges") {
test("handle deep merges") {
val scala = json"""
{
"name": "scala",
Expand Down Expand Up @@ -281,6 +281,15 @@ class DijonSpec extends FunSuite {

assert(scala == scalaCopy) // original json objects stay untouched after merging
assert(java == javaCopy)

val ab = json"""{"a":{"b":[0,1]}}"""
val ac = json"""{"a":{"c":[1,2]}}"""
val `ab++ac` = ab ++ ac // merge result should be not affected by subsequent mutation of arguments
ab.a.b(0) = json"""5"""
ac.a.c(0) = json"""3"""
assert(ab == json"""{"a":{"b":[5,1]}}""")
assert(ac == json"""{"a":{"c":[3,2]}}""")
assert(`ab++ac` == json"""{"a":{"b":[0,1],"c":[1,2]}}""")
}

test("be type-safeish") {
Expand Down

0 comments on commit e4c8b61

Please sign in to comment.