From 4a769764836a14ca3afa4d6a6f7f09943e290ec2 Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Thu, 12 Apr 2018 13:59:43 +0700 Subject: Fixed merge JsValues when field is absent in old value (#153) --- src/main/scala/xyz/driver/core/rest/PatchDirectives.scala | 8 ++++---- src/test/scala/xyz/driver/core/rest/PatchDirectivesTest.scala | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/scala/xyz/driver/core/rest/PatchDirectives.scala b/src/main/scala/xyz/driver/core/rest/PatchDirectives.scala index 256358c..f33bf9d 100644 --- a/src/main/scala/xyz/driver/core/rest/PatchDirectives.scala +++ b/src/main/scala/xyz/driver/core/rest/PatchDirectives.scala @@ -53,10 +53,10 @@ trait PatchDirectives extends Directives with SprayJsonSupport { } protected def mergeObjects(oldObj: JsObject, newObj: JsObject, maxLevels: Option[Int] = None): JsObject = { - JsObject(oldObj.fields.map({ - case (key, oldValue) => - val newValue = newObj.fields.get(key).fold(oldValue)(mergeJsValues(oldValue, _, maxLevels.map(_ - 1))) - key -> newValue + JsObject((oldObj.fields.keys ++ newObj.fields.keys).map({ key => + val oldValue = oldObj.fields.getOrElse(key, JsNull) + val newValue = newObj.fields.get(key).fold(oldValue)(mergeJsValues(oldValue, _, maxLevels.map(_ - 1))) + key -> newValue })(collection.breakOut): _*) } diff --git a/src/test/scala/xyz/driver/core/rest/PatchDirectivesTest.scala b/src/test/scala/xyz/driver/core/rest/PatchDirectivesTest.scala index 6a6b035..987717d 100644 --- a/src/test/scala/xyz/driver/core/rest/PatchDirectivesTest.scala +++ b/src/test/scala/xyz/driver/core/rest/PatchDirectivesTest.scala @@ -72,6 +72,15 @@ class PatchDirectivesTest } } + it should "handle optional values correctly when old value is null" in { + val fooRetrieve = Future.successful(Some(testFoo.copy(bar = None))) + + Patch("/api/v1/foos/1", jsonEntity("""{"bar": {"name": "My Bar","size":10}}""")) ~> route(fooRetrieve) ~> check { + handled shouldBe true + responseAs[Foo] shouldBe testFoo.copy(bar = Some(Bar(Name("My Bar"), 10))) + } + } + it should "return a 400 for nulls on non-optional values" in { val fooRetrieve = Future.successful(Some(testFoo)) -- cgit v1.2.3