From e99044595837448dd934a0e177636b35643651ca Mon Sep 17 00:00:00 2001
From: Michael Kimsal <michael@kimsal.com>
Date: Thu, 19 Aug 2021 10:57:41 -0400
Subject: [PATCH] fix: removeNullProperties filtered out regular arrays

Existing removeNullProperties filtered out standard arrays, causing problems.  Specifically, an $invoice object with $customerRef on it (with $customerRef['value']) was filtered out, causing "CustomerRef is missing" validation errors.

I added the count() check to ignore empty array values, which seems in spirit with the 'removeNull' intention.

Adding a test, based on the previously added testThatRemoveNullPropertiesLeavesNonNullValuesInPlace
---
 .../Serialization/JsonObjectSerializer.php    |  6 +++-
 src/Utility.Test/JsonObjectSerializerTest.php | 30 +++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/src/Core/Http/Serialization/JsonObjectSerializer.php b/src/Core/Http/Serialization/JsonObjectSerializer.php
index 5176a260..56be8682 100644
--- a/src/Core/Http/Serialization/JsonObjectSerializer.php
+++ b/src/Core/Http/Serialization/JsonObjectSerializer.php
@@ -201,12 +201,16 @@ private function removeNullProperties($val){
         $returned = array();
         foreach($filterArray as $k => $v){
           if(is_array($v)){
-            if(FacadeHelper::isRecurrsiveArray($v)){
+            if(count($v)>0 && FacadeHelper::isRecurrsiveArray($v)){
               $list = array();
               foreach($v as $kk => $vv){
                   $list[] = array_filter($vv, [self::class, 'valueIsNotNullOrEmptyString']);
               }
               $returned[$k] = $list;
+            } else {
+                if (count($v) > 0) {
+                    $returned[$k] = $v;
+                }
             }
           }else{
             $returned[$k] = $v;
diff --git a/src/Utility.Test/JsonObjectSerializerTest.php b/src/Utility.Test/JsonObjectSerializerTest.php
index f0f686ed..871586d6 100644
--- a/src/Utility.Test/JsonObjectSerializerTest.php
+++ b/src/Utility.Test/JsonObjectSerializerTest.php
@@ -214,4 +214,34 @@ public function testThatRemoveNullPropertiesLeavesNonNullValuesInPlace() {
         $this->assertFalse(isset($customerWithNullPropertiesRemoved['Suffix']));
         $this->assertFalse(isset($customerWithNullPropertiesRemoved['Notes']));
     }
+
+    /**
+     * Test demonstrates that passing in a non-recursive array to the 'removeNullProperties' method
+     * will still return non-recursive arrays (like a 'CustomerRef' on an 'Invoice')
+     *
+     * Empty arrays will be filtered out
+     *
+     * @throws ReflectionException
+     */
+    public function testThatRemoveNullPropertiesLeavesStandardArraysInPlace() {
+        $invoice = [
+            "Type" => "InvoiceType",
+            "Lines" => [],
+            "CustomerRef" => [
+                'name' => 'Customer',
+                'value' => '17',
+            ],
+        ];
+
+        $jsonSerializer = new JsonObjectSerializer();
+        $removeNullPropertiesMethod = new ReflectionMethod($jsonSerializer, 'removeNullProperties');
+        $removeNullPropertiesMethod->setAccessible(true);
+
+        $serializedInvoice = $removeNullPropertiesMethod->invoke($jsonSerializer, $invoice);
+
+        // Make sure that the null and empty-string properties were removed, but all others remain
+        $this->assertArrayHasKey('CustomerRef', $serializedInvoice);
+        $this->assertArrayNotHasKey('Lines', $serializedInvoice);
+        $this->assertEquals($invoice['CustomerRef']['name'], $serializedInvoice['CustomerRef']['name']);
+    }
 }