You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by bs...@apache.org on 2019/03/14 22:59:19 UTC

[geode] branch develop updated: GEODE-5013 Replace org.json with Jackson in GfJsonObject

This is an automated email from the ASF dual-hosted git repository.

bschuchardt pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new aa38e22  GEODE-5013 Replace org.json with Jackson in GfJsonObject
aa38e22 is described below

commit aa38e224f484d22def2bae2ff940715f2ab86de9
Author: Bruce Schuchardt <bs...@pivotal.io>
AuthorDate: Thu Mar 14 15:56:29 2019 -0700

    GEODE-5013 Replace org.json with Jackson in GfJsonObject
    
    This removes org.json as a dependency in geode-core and associated test
    modules.  GfJsonObject and GfJsonArray are ported to use the same basic
    Jackson ObjectMapper setup as QueryResultFormatter so that we now have a
    uniform mechanism for managing JSON documents for querying/gfsh and
    folks can use Jackson annotations like @JsonIgnore on their classes.
    
    The geode-web-api and geode-pulse modules still use the geode-json
    module in tests.  When/if they are ported to use GfJsonObject/Array we can delete
    the geode-json module.
---
 geode-core/build.gradle                            |   1 -
 .../geode/management/QueryDataDUnitTest.java       |  27 +-
 .../geode/pdx/JSONPdxClientServerDUnitTest.java    |   5 +-
 .../management/DataQueryEngineIntegrationTest.java |  26 +-
 .../apache/geode/pdx/JSONFormatterJUnitTest.java   |   8 +-
 .../apache/geode/codeAnalysis/excludedClasses.txt  |   2 +-
 .../codeAnalysis/sanctionedDataSerializables.txt   |   2 +-
 .../apache/geode/distributed/LocatorLauncher.java  |   3 +-
 .../apache/geode/distributed/ServerLauncher.java   |   3 +-
 .../membership/gms/membership/GMSJoinLeave.java    |   2 -
 .../geode/internal/cache/versions/VersionTag.java  |   3 +-
 ...ltFormatter.java => AbstractJSONFormatter.java} | 140 ++-----
 .../management/internal/cli/json/GfJsonArray.java  | 150 +++----
 .../management/internal/cli/json/GfJsonObject.java | 344 ++++++++--------
 .../internal/cli/json/QueryResultFormatter.java    | 290 +-------------
 .../internal/cli/result/AbstractResultData.java    |  10 +-
 .../internal/cli/result/CompositeResultData.java   |  15 -
 .../internal/cli/result/ErrorResultData.java       |   6 +-
 .../internal/cli/result/LegacyCommandResult.java   |  30 +-
 .../internal/cli/result/ResultBuilder.java         |   2 +-
 .../management/internal/cli/result/ResultData.java |   6 +
 .../internal/cli/result/TabularResultData.java     |   2 +-
 .../geode/management/internal/cli/shell/Gfsh.java  |   3 +-
 .../management/internal/cli/util/JsonUtil.java     | 432 +++++++--------------
 .../AbstractLauncherServiceStateTest.java          |   4 +-
 .../internal/cli/json/GfJsonArrayTest.java         |  67 +---
 .../internal/cli/json/GfJsonObjectTest.java        |  36 ++
 .../internal/cli/result/InfoResultDataTest.java    |   8 +-
 geode-core/src/test/resources/expected-pom.xml     |   5 -
 geode-dunit/build.gradle                           |   1 -
 .../apache/geode/pdx/JSONFormatVerifyUtility.java  |  30 +-
 geode-dunit/src/test/resources/expected-pom.xml    |   5 -
 .../geode/pdx/TestObjectForJSONFormatter.java      |  13 +-
 geode-web-api/build.gradle                         |   2 +
 .../geode/test/matchers/JsonEquivalence.java       |   0
 35 files changed, 598 insertions(+), 1085 deletions(-)

diff --git a/geode-core/build.gradle b/geode-core/build.gradle
index 91cbcd4..caf08a5 100755
--- a/geode-core/build.gradle
+++ b/geode-core/build.gradle
@@ -269,7 +269,6 @@ dependencies {
   compile('com.healthmarketscience.rmiio:rmiio')
 
   compile(project(':geode-common'))
-  compile(project(':geode-json'))
   compile(project(':geode-management'))
 
   jcaAnnotationProcessor 'org.apache.logging.log4j:log4j-core'
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/management/QueryDataDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/management/QueryDataDUnitTest.java
index fa037cd..61d3d9a 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/management/QueryDataDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/management/QueryDataDUnitTest.java
@@ -37,9 +37,6 @@ import java.util.concurrent.TimeoutException;
 
 import javax.management.ObjectName;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -64,6 +61,8 @@ import org.apache.geode.internal.cache.partitioned.fixed.SingleHopQuarterPartiti
 import org.apache.geode.management.internal.SystemManagementService;
 import org.apache.geode.management.internal.beans.BeanUtilFuncs;
 import org.apache.geode.management.internal.beans.QueryDataFunction;
+import org.apache.geode.management.internal.cli.json.GfJsonArray;
+import org.apache.geode.management.internal.cli.json.GfJsonObject;
 import org.apache.geode.pdx.PdxInstance;
 import org.apache.geode.pdx.PdxInstanceFactory;
 import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl;
@@ -72,7 +71,7 @@ import org.apache.geode.test.dunit.rules.DistributedUseJacksonForJsonPathRule;
 import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
 
 /**
- * Distributed tests for {@link DistributedSystemMXBean#queryData(String, String, int)}.
+ * Distributed tests for DistributedSystemMXBean#queryData(String, String, int).
  * </p>
  *
  * <pre>
@@ -246,16 +245,17 @@ public class QueryDataDUnitTest implements Serializable {
       assertThat(jsonString).contains("result").doesNotContain("No Data Found");
       assertThat(jsonString).contains(BIG_COLLECTION_ELEMENT_);
 
-      JSONObject jsonObject = new JSONObject(jsonString);
-      JSONArray jsonArray = jsonObject.getJSONArray("result");
+      GfJsonObject jsonObject = new GfJsonObject(jsonString);
+      GfJsonArray jsonArray = jsonObject.getJSONArray("result");
       assertThat(jsonArray.length()).isEqualTo(DEFAULT_QUERY_LIMIT);
 
       // Get the first element
-      JSONArray jsonArray1 = jsonArray.getJSONArray(0);
+      GfJsonArray jsonArray1 = jsonArray.getJSONArray(0);
+      assertThat(jsonArray1).isNotNull();
 
       // Get the ObjectValue
-      JSONObject collectionObject = (JSONObject) jsonArray1.get(1);
-      assertThat(collectionObject.length()).isEqualTo(100);
+      GfJsonObject collectionObject = jsonArray1.getInternalJsonObject(1);
+      assertThat(collectionObject.size()).isEqualTo(100);
 
       // Query With Override Values
       int newQueryCollectionDepth = 150;
@@ -274,7 +274,7 @@ public class QueryDataDUnitTest implements Serializable {
       verifyJsonIsValid(jsonString);
       assertThat(jsonString).contains("result").doesNotContain("No Data Found");
 
-      jsonObject = new JSONObject(jsonString);
+      jsonObject = new GfJsonObject(jsonString);
       assertThat(jsonString).contains(BIG_COLLECTION_ELEMENT_);
 
       jsonArray = jsonObject.getJSONArray("result");
@@ -284,8 +284,8 @@ public class QueryDataDUnitTest implements Serializable {
       jsonArray1 = jsonArray.getJSONArray(0);
 
       // Get the ObjectValue
-      collectionObject = (JSONObject) jsonArray1.get(1);
-      assertThat(collectionObject.length()).isEqualTo(newQueryCollectionDepth);
+      collectionObject = jsonArray1.getInternalJsonObject(1);
+      assertThat(collectionObject.size()).isEqualTo(newQueryCollectionDepth);
     });
   }
 
@@ -482,10 +482,9 @@ public class QueryDataDUnitTest implements Serializable {
     return calendar.getTime();
   }
 
-  private void verifyJsonIsValid(final String jsonString) throws JSONException {
+  private void verifyJsonIsValid(final String jsonString) {
     assertThat(jsonString, isJson());
     assertThat(jsonString, hasJsonPath("$.result"));
-    assertThat(new JSONObject(jsonString)).isNotNull();
   }
 
   private void putDataInRegion(final String regionName, final Object[] portfolio, final int from,
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
index 80955fa..3a622c4 100755
--- a/geode-core/src/distributedTest/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
@@ -44,6 +44,7 @@ import org.apache.geode.cache.server.CacheServer;
 import org.apache.geode.internal.Assert;
 import org.apache.geode.internal.AvailablePortHelper;
 import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.pdx.internal.json.PdxToJSON;
 import org.apache.geode.test.dunit.Host;
 import org.apache.geode.test.dunit.NetworkUtils;
@@ -184,7 +185,7 @@ public class JSONPdxClientServerDUnitTest extends JUnit4CacheTestCase {
     });
   }
 
-  public void VerifyPdxInstanceAndJsonConversion() throws JsonProcessingException {
+  public void VerifyPdxInstanceAndJsonConversion() throws JsonProcessingException, GfJsonException {
     Region region = getRootRegion("testSimplePdx");
 
     // Create Object and initialize its members.
@@ -214,7 +215,7 @@ public class JSONPdxClientServerDUnitTest extends JUnit4CacheTestCase {
   }
 
   private void validateReceivedJSON(Region region, TestObjectForJSONFormatter actualTestObject,
-      ObjectMapper objectMapper) throws JsonProcessingException {
+      ObjectMapper objectMapper) throws JsonProcessingException, GfJsonException {
     // 1. get the json from the object using Jackson Object Mapper
     String json = objectMapper.writeValueAsString(actualTestObject);
     String jsonWithClassType = actualTestObject.addClassTypeToJson(json);
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/management/DataQueryEngineIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/management/DataQueryEngineIntegrationTest.java
index 43be476..d2d9091 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/management/DataQueryEngineIntegrationTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/management/DataQueryEngineIntegrationTest.java
@@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.util.ArrayList;
 import java.util.Collection;
 
-import org.json.JSONObject;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -33,6 +32,7 @@ import org.apache.geode.management.internal.ManagementConstants;
 import org.apache.geode.management.internal.SystemManagementService;
 import org.apache.geode.management.internal.beans.DataQueryEngine;
 import org.apache.geode.management.internal.beans.QueryDataFunction;
+import org.apache.geode.management.internal.cli.json.GfJsonObject;
 import org.apache.geode.management.model.EmptyObject;
 import org.apache.geode.management.model.Item;
 import org.apache.geode.management.model.Order;
@@ -105,7 +105,7 @@ public class DataQueryEngineIntegrationTest {
 
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   /**
@@ -135,7 +135,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   /**
@@ -165,7 +165,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -189,7 +189,7 @@ public class DataQueryEngineIntegrationTest {
     System.out.println("Query Result: " + queryResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -215,7 +215,7 @@ public class DataQueryEngineIntegrationTest {
     System.out.println("Query Result: " + queryResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -241,7 +241,7 @@ public class DataQueryEngineIntegrationTest {
     System.out.println("Query Result: " + queryResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
 
   }
 
@@ -254,7 +254,7 @@ public class DataQueryEngineIntegrationTest {
     System.out.println(queryResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -267,7 +267,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -281,7 +281,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -304,7 +304,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -322,7 +322,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
   @Test
@@ -340,7 +340,7 @@ public class DataQueryEngineIntegrationTest {
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
-    new JSONObject(queryResult);
+    new GfJsonObject(queryResult);
   }
 
 
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
index 925597a..5eb0cb3 100755
--- a/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
@@ -24,7 +24,6 @@ import java.util.List;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.json.JSONException;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,6 +33,7 @@ import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.CacheFactory;
 import org.apache.geode.cache.DataPolicy;
 import org.apache.geode.cache.Region;
+import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.pdx.internal.PdxInstanceImpl;
 import org.apache.geode.pdx.internal.PeerTypeRegistration;
 import org.apache.geode.test.junit.categories.SerializationTest;
@@ -58,7 +58,7 @@ public class JSONFormatterJUnitTest {
   }
 
   @Test
-  public void ValidatePdxInstanceToJsonConversion() {
+  public void ValidatePdxInstanceToJsonConversion() throws GfJsonException {
     TestObjectForJSONFormatter actualTestObject = new TestObjectForJSONFormatter();
     actualTestObject.defaultInitialization();
 
@@ -78,7 +78,7 @@ public class JSONFormatterJUnitTest {
   }
 
   @Test
-  public void verifyJsonToPdxInstanceConversion() throws JSONException, JsonProcessingException {
+  public void verifyJsonToPdxInstanceConversion() throws JsonProcessingException, GfJsonException {
     TestObjectForJSONFormatter expectedTestObject = new TestObjectForJSONFormatter();
     expectedTestObject.defaultInitialization();
 
@@ -113,7 +113,7 @@ public class JSONFormatterJUnitTest {
   }
 
   @Test
-  public void verifyJsonToPdxInstanceConversionWithJSONFormatter() {
+  public void verifyJsonToPdxInstanceConversionWithJSONFormatter() throws GfJsonException {
     TestObjectForJSONFormatter expectedTestObject = new TestObjectForJSONFormatter();
     expectedTestObject.defaultInitialization();
 
diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/excludedClasses.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/excludedClasses.txt
index 1b1eb9f..1c986da 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/excludedClasses.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/excludedClasses.txt
@@ -68,7 +68,7 @@ org/apache/geode/internal/tcp/VersionedByteBufferInputStream
 org/apache/geode/internal/util/concurrent/StoppableReadWriteLock
 org/apache/geode/management/internal/cli/commands/ShowMetricsCommand$Category
 org/apache/geode/management/internal/cli/exceptions/UserErrorException
-org/apache/geode/management/internal/cli/json/QueryResultFormatter$PreventReserializationModule
+org/apache/geode/management/internal/cli/json/AbstractJSONFormatter$PreventReserializationModule
 org/apache/geode/security/ResourcePermission
 org/apache/geode/security/ResourcePermission$Operation
 org/apache/geode/security/ResourcePermission$Resource
diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 8a91b84..e035104 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1981,7 +1981,7 @@ fromData,212
 toData,239
 
 org/apache/geode/internal/cache/versions/VersionTag,2
-fromData,187
+fromData,189
 toData,259
 
 org/apache/geode/internal/cache/wan/GatewaySenderAdvisor$GatewaySenderProfile,4
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java b/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java
index 7ea24fe..cb7a7d9 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java
@@ -78,7 +78,6 @@ import org.apache.geode.internal.process.ProcessType;
 import org.apache.geode.internal.process.ProcessUtils;
 import org.apache.geode.internal.process.UnableToControlProcessException;
 import org.apache.geode.lang.AttachAPINotFoundException;
-import org.apache.geode.management.internal.cli.json.GfJsonArray;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 import org.apache.geode.management.internal.cli.util.HostUtils;
@@ -2001,7 +2000,7 @@ public class LocatorLauncher extends AbstractLauncher<String> {
         final Status status = Status.valueOfDescription(gfJsonObject.getString(JSON_STATUS));
 
         final List<String> jvmArguments =
-            Arrays.asList(GfJsonArray.toStringArray(gfJsonObject.getJSONArray(JSON_JVMARGUMENTS)));
+            gfJsonObject.getJSONArray(JSON_JVMARGUMENTS).toStringList();
 
         return new LocatorState(status, gfJsonObject.getString(JSON_STATUSMESSAGE),
             gfJsonObject.getLong(JSON_TIMESTAMP), gfJsonObject.getString(JSON_LOCATION),
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java b/geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java
index 9edee8b..a12de6e 100755
--- a/geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/ServerLauncher.java
@@ -85,7 +85,6 @@ import org.apache.geode.internal.process.ProcessType;
 import org.apache.geode.internal.process.UnableToControlProcessException;
 import org.apache.geode.lang.AttachAPINotFoundException;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.json.GfJsonArray;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 import org.apache.geode.management.internal.cli.util.HostUtils;
@@ -2596,7 +2595,7 @@ public class ServerLauncher extends AbstractLauncher<String> {
 
         final Status status = Status.valueOfDescription(gfJsonObject.getString(JSON_STATUS));
         final List<String> jvmArguments =
-            Arrays.asList(GfJsonArray.toStringArray(gfJsonObject.getJSONArray(JSON_JVMARGUMENTS)));
+            gfJsonObject.getJSONArray(JSON_JVMARGUMENTS).toStringList();
 
         return new ServerState(status, gfJsonObject.getString(JSON_STATUSMESSAGE),
             gfJsonObject.getLong(JSON_TIMESTAMP), gfJsonObject.getString(JSON_LOCATION),
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
index a816e78..0aa6b13 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
@@ -1078,8 +1078,6 @@ public class GMSJoinLeave implements JoinLeave, MessageHandler {
   private void forceDisconnect(String reason) {
     this.isStopping = true;
     if (!isJoined) {
-      logger.fatal("BRUCE: forcedDisconnect invoked.  isReconnecting={} isJoined={}",
-          services.getConfig().isReconnecting(), isJoined);
       joinResponse[0] =
           new JoinResponseMessage(
               "Stopping due to ForcedDisconnectException caused by '" + reason + "'", -1);
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/versions/VersionTag.java b/geode-core/src/main/java/org/apache/geode/internal/cache/versions/VersionTag.java
index f34f4d9..2329cd6 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/versions/VersionTag.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/versions/VersionTag.java
@@ -408,9 +408,10 @@ public abstract class VersionTag<T extends VersionSource>
         this.previousMemberID = readMember(in);
       }
     }
-    setIsRemoteForTesting();
+    setBits(BITS_IS_REMOTE_TAG);
   }
 
+  /** for unit testing receipt of version tags from another member of the cluster */
   public void setIsRemoteForTesting() {
     setBits(BITS_IS_REMOTE_TAG);
   }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/AbstractJSONFormatter.java
similarity index 74%
copy from geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java
copy to geode-core/src/main/java/org/apache/geode/management/internal/cli/json/AbstractJSONFormatter.java
index 1720902..5698a4c 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/AbstractJSONFormatter.java
@@ -14,15 +14,11 @@
  */
 package org.apache.geode.management.internal.cli.json;
 
+
 import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
 import com.fasterxml.jackson.core.JsonGenerator;
@@ -43,52 +39,37 @@ import org.apache.geode.cache.Region;
 import org.apache.geode.cache.query.internal.StructImpl;
 import org.apache.geode.pdx.PdxInstance;
 
-/**
- * A JSON serializer that has special handling for collections to limit the number of elements
- * written to the document. It also has special handling for PdxInstance and query Structs.
- */
-public class QueryResultFormatter {
-
-  private final ObjectMapper mapper;
+public abstract class AbstractJSONFormatter {
 
-  /**
-   * map contains the named objects to be serialized
-   */
-  private final Map<String, List<Object>> map;
+  final ObjectMapper mapper;
 
   /**
    * serializedObjects is used to prevent recursive serialization in cases where
    * there are cyclical references
    */
-  private final Map<Object, Object> serializedObjects;
-
-  /**
-   * Create a formatter that will limit collection sizes to maxCollectionElements
-   * and will limit object traversal to being the same but in depth.
-   *
-   * @param maxCollectionElements limit on collection elements and depth-first object traversal
-   */
-  public QueryResultFormatter(int maxCollectionElements) {
-    this(maxCollectionElements, maxCollectionElements);
-  }
+  final Map<Object, Object> serializedObjects;
 
   /**
    * Create a formatter that will limit collection sizes to maxCollectionElements
    *
    * @param maxCollectionElements limit on collection elements
    * @param serializationDepth when traversing objects, how deep should we go?
+   * @param generateTypeInformation whether generated JSON should have java type information
    */
-  private QueryResultFormatter(int maxCollectionElements, int serializationDepth) {
-    this.map = new LinkedHashMap<>();
+  public AbstractJSONFormatter(int maxCollectionElements, int serializationDepth,
+      boolean generateTypeInformation) {
+
+    int serDepth = serializationDepth < 0 ? Integer.MAX_VALUE : serializationDepth;
+    int maxElements = maxCollectionElements < 0 ? Integer.MAX_VALUE : maxCollectionElements;
 
     this.serializedObjects = new IdentityHashMap<>();
     this.mapper = new ObjectMapper();
 
     SimpleModule mapperModule =
-        new PreventReserializationModule(serializedObjects, serializationDepth);
+        new PreventReserializationModule(serializedObjects, serDepth);
 
     // insert a collection serializer that limits the number of elements generated
-    mapperModule.addSerializer(Collection.class, new CollectionSerializer(maxCollectionElements));
+    mapperModule.addSerializer(Collection.class, new CollectionSerializer(maxElements));
     // insert a PdxInstance serializer that knows about PDX fields/values
     mapperModule.addSerializer(PdxInstance.class, new PdxInstanceSerializer());
     // insert a Struct serializer that knows about its format
@@ -104,86 +85,19 @@ public class QueryResultFormatter {
     mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
     // sort fields alphabetically
     mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
-    // add type information (Jackson has no way to force it to do this for all values)
-    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
 
-  }
-
-  /**
-   * After instantiating a formatter add the objects you want to be formatted
-   * using this method. Typically this will be add("result", queryResult)
-   */
-  public synchronized QueryResultFormatter add(String key, Object value) {
-    List<Object> list = this.map.get(key);
-    if (list != null) {
-      list.add(value);
-    } else {
-      list = new ArrayList<>();
-      if (value != null) {
-        list.add(value);
-      }
-      this.map.put(key, list);
+    if (generateTypeInformation) {
+      // add type information (Jackson has no way to force it to do this for all values)
+      mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
     }
-    return this;
-  }
-
-  /* non-javadoc use Jackson to serialize added objects into JSON format */
-  @Override
-  public synchronized String toString() {
-    Writer writer = new StringWriter();
-    try {
-      boolean addComma = false;
-      writer.write('{');
-      for (Map.Entry<String, List<Object>> entry : this.map.entrySet()) {
-        if (addComma) {
-          writer.write(',');
-        }
-        mapper.writerFor(entry.getKey().getClass()).writeValue(writer, entry.getKey());
-        writer.write(':');
-        writeList(writer, entry.getValue());
-        addComma = true;
-      }
-      writer.write('}');
+    postCreateMapper();
 
-      return writer.toString();
-    } catch (IOException exception) {
-      new GfJsonException(exception).printStackTrace();
-    } catch (GfJsonException e) {
-      e.printStackTrace();
-    }
-    return null;
   }
 
-
-  private Writer writeList(Writer writer, List<Object> values) throws GfJsonException {
-    // for each object we clear out the serializedObjects recursion map so that
-    // we don't immediately see "duplicate" entries
-    serializedObjects.clear();
-    try {
-      boolean addComma = false;
-      int length = values.size();
-      writer.write('[');
-
-      if (length == 0) {
-        mapper.writeValue(writer, null);
-      } else {
-        for (int i = 0; i < length; i += 1) {
-          if (addComma) {
-            writer.write(',');
-          }
-          mapper.writerFor(values.get(i).getClass()).writeValue(writer, values.get(i));
-
-          addComma = true;
-        }
-      }
-      writer.write(']');
-    } catch (IOException e) {
-      throw new GfJsonException(e);
-    }
-    return writer;
+  void postCreateMapper() {
+    // let subclasses modify the mapper
   }
 
-
   private static class PreventReserializationSerializer extends JsonSerializer {
 
     private JsonSerializer defaultSerializer;
@@ -269,7 +183,7 @@ public class QueryResultFormatter {
       gen.setCurrentValue(value);
       WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
           typeSer.typeId(value, JsonToken.START_OBJECT));
-      _serialize(value, gen);
+      serializeElements(value, gen);
       typeSer.writeTypeSuffix(gen, typeIdDef);
     }
 
@@ -277,11 +191,11 @@ public class QueryResultFormatter {
     public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers)
         throws IOException {
       gen.writeStartObject();
-      _serialize(value, gen);
+      serializeElements(value, gen);
       gen.writeEndObject();
     }
 
-    void _serialize(Collection value, JsonGenerator gen) throws IOException {
+    void serializeElements(Collection value, JsonGenerator gen) throws IOException {
       Iterator<Object> objects = value.iterator();
       for (int i = 0; i < maxCollectionElements && objects.hasNext(); i++) {
         Object nextObject = objects.next();
@@ -303,7 +217,7 @@ public class QueryResultFormatter {
         throws IOException {
       WritableTypeId writableTypeId = typeSer.typeId(value, JsonToken.START_OBJECT);
       typeSer.writeTypePrefix(gen, writableTypeId);
-      _serialize(value, gen);
+      serializeFields(value, gen);
       typeSer.writeTypeSuffix(gen, writableTypeId);
     }
 
@@ -311,11 +225,11 @@ public class QueryResultFormatter {
     public void serialize(PdxInstance value, JsonGenerator gen, SerializerProvider serializers)
         throws IOException {
       gen.writeStartObject();
-      _serialize(value, gen);
+      serializeFields(value, gen);
       gen.writeEndObject();
     }
 
-    void _serialize(PdxInstance value, JsonGenerator gen) throws IOException {
+    void serializeFields(PdxInstance value, JsonGenerator gen) throws IOException {
       for (String field : value.getFieldNames()) {
         gen.writeObjectField(field, value.getField(field));
       }
@@ -333,7 +247,7 @@ public class QueryResultFormatter {
         SerializerProvider serializers, TypeSerializer typeSer)
         throws IOException {
       typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.START_OBJECT));
-      _serialize(value, gen);
+      serializeElements(value, gen);
       typeSer.writeTypeSuffix(gen, typeSer.typeId(value, JsonToken.START_OBJECT));
     }
 
@@ -341,11 +255,11 @@ public class QueryResultFormatter {
     public void serialize(StructImpl value, JsonGenerator gen, SerializerProvider serializers)
         throws IOException {
       gen.writeStartObject();
-      _serialize(value, gen);
+      serializeElements(value, gen);
       gen.writeEndObject();
     }
 
-    void _serialize(StructImpl value, JsonGenerator gen) throws IOException {
+    void serializeElements(StructImpl value, JsonGenerator gen) throws IOException {
       String[] fields = value.getFieldNames();
       Object[] values = value.getFieldValues();
       for (int i = 0; i < fields.length; i++) {
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonArray.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonArray.java
index 593192a..af90541 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonArray.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonArray.java
@@ -14,12 +14,14 @@
  */
 package org.apache.geode.management.internal.cli.json;
 
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import org.apache.logging.log4j.Logger;
-import org.json.JSONArray;
-import org.json.JSONException;
 
 import org.apache.geode.internal.logging.LogService;
 
@@ -29,109 +31,111 @@ import org.apache.geode.internal.logging.LogService;
  *
  * @since GemFire 7.0
  */
-public class GfJsonArray {
+public class GfJsonArray extends AbstractJSONFormatter {
   private static final Logger logger = LogService.getLogger();
 
-  private JSONArray jsonArray;
+  private final ArrayNode jsonArray;
 
   public GfJsonArray() {
-    this.jsonArray = new JSONArray();
+    super(-1, -1, false);
+    this.jsonArray = mapper.createArrayNode();
   }
 
   /**
    * @throws GfJsonException If not an array.
    */
   public GfJsonArray(Object array) throws GfJsonException {
+    super(-1, -1, false);
     try {
-      if (array instanceof JSONArray) {
-        this.jsonArray = (JSONArray) array;
+      if (array instanceof ArrayNode) {
+        this.jsonArray = (ArrayNode) array;
       } else {
-        this.jsonArray = new JSONArray(array);
+        this.jsonArray = mapper.valueToTree(array);
       }
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      if (this.jsonArray == null) {
+        throw new IllegalArgumentException("Array translated into null JSON node: " + array);
+      }
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
   }
 
+  void postCreateMapper() {
+    mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+    mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+  }
+
   /**
    * Get the object value associated with an index.
    *
    * @return An object value.
    * @throws GfJsonException If there is no value for the index.
    */
-  public Object get(int index) throws GfJsonException {
+  public String getString(int index) throws GfJsonException {
     try {
-      return this.jsonArray.get(index);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      JsonNode node = jsonArray.get(index);
+      if (node.textValue() != null) {
+        return node.asText();
+      } else {
+        return node.toString();
+      }
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
   }
 
-  public GfJsonObject getJSONObject(int index) throws GfJsonException {
+  public GfJsonObject getInternalJsonObject(int index) throws GfJsonException {
     try {
-      return new GfJsonObject(jsonArray.getJSONObject(index));
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      return new GfJsonObject(jsonArray.get(index));
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
   }
 
   public GfJsonArray put(Object value) {
-    this.jsonArray.put(extractInternalForGfJsonOrReturnSame(value));
-
-    return this;
-  }
-
-  /**
-   * @return this GfJsonArray
-   * @throws GfJsonException If the index is negative or if the the value is an invalid number.
-   */
-  public GfJsonArray put(int index, Object value) throws GfJsonException {
-    try {
-      this.jsonArray.put(index, extractInternalForGfJsonOrReturnSame(value));
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
-    }
+    this.jsonArray.add(toJsonNode(value));
     return this;
   }
 
-  public GfJsonArray put(Collection<?> value) {
-    this.jsonArray.put(value);
-    return this;
+  public int length() {
+    return this.jsonArray.size();
   }
 
   /**
    * @return this GfJsonArray
-   * @throws GfJsonException If the index is negative or if the value is not finite.
+   * @throws GfJsonException If the index is negative or if the the value is an invalid number.
    */
-  public GfJsonArray put(int index, Collection<?> value) throws GfJsonException {
+  public GfJsonArray put(int index, Object value) throws GfJsonException {
+    JsonNode json = null;
     try {
-      this.jsonArray.put(index, value);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      json = toJsonNode(value);
+      this.jsonArray.set(index, json);
+    } catch (IndexOutOfBoundsException e) {
+      while (this.jsonArray.size() < index) {
+        this.jsonArray.add((JsonNode) null);
+      }
+      this.jsonArray.add(json);
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
 
-  public GfJsonArray put(Map<?, ?> value) {
-    this.jsonArray.put(value);
-    return this;
-  }
-
   /**
    * @return this GfJsonArray
    * @throws GfJsonException If the index is negative or if the the value is an invalid number.
    */
   public GfJsonArray put(int index, Map<?, ?> value) throws GfJsonException {
     try {
-      this.jsonArray.put(index, value);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      this.jsonArray.set(index, toJsonNode(value));
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
 
   public int size() {
-    return jsonArray.length();
+    return jsonArray.size();
   }
 
   @Override
@@ -147,7 +151,7 @@ public class GfJsonArray {
       byteArray = new byte[length];
       for (int i = 0; i < length; i++) {
         try {
-          byteArray[i] = Byte.valueOf(String.valueOf(jsonArray.get(i)));
+          byteArray[i] = Byte.valueOf(String.valueOf(jsonArray.getString(i)));
         } catch (GfJsonException e) {
           throw new GfJsonException(e.getMessage());
         }
@@ -157,38 +161,38 @@ public class GfJsonArray {
     return byteArray;
   }
 
-  public static String[] toStringArray(GfJsonArray jsonArray) {
-    String[] stringArray = null;
-    if (jsonArray != null) {
-      int length = jsonArray.size();
-      stringArray = new String[length];
-      for (int i = 0; i < length; i++) {
-        try {
-          stringArray[i] = String.valueOf(jsonArray.get(i));
-        } catch (GfJsonException e) {
-          logger.info("", e);
-          stringArray = null;
-        }
+  public List<String> toStringList() {
+    List<String> stringArray = null;
+    int length = jsonArray.size();
+    stringArray = new ArrayList<>(length);
+    for (int i = 0; i < length; i++) {
+      try {
+        stringArray.add(getString(i));
+      } catch (GfJsonException e) {
+        logger.info("", e);
+        stringArray = null;
       }
     }
-
     return stringArray;
   }
 
-  public JSONArray getInternalJsonArray() {
+  public ArrayNode getInternalJsonArray() {
     return jsonArray;
   }
 
-  private static Object extractInternalForGfJsonOrReturnSame(Object value) {
-    Object returnedValue = value;
+  private JsonNode toJsonNode(Object value) {
     if (value instanceof GfJsonObject) {
-      returnedValue = ((GfJsonObject) value).getInternalJsonObject();
-    } else if (value instanceof GfJsonArray) {
-      returnedValue = ((GfJsonArray) value).getInternalJsonArray();
+      return ((GfJsonObject) value).getInternalJsonObject();
+    }
+    if (value instanceof GfJsonArray) {
+      return ((GfJsonArray) value).getInternalJsonArray();
     } else if (value == null) {
-      returnedValue = GfJsonObject.NULL;
+      return mapper.valueToTree(GfJsonObject.NULL);
     }
+    return mapper.valueToTree(value);
+  }
 
-    return returnedValue;
+  public GfJsonArray getJSONArray(int i) throws GfJsonException {
+    return new GfJsonArray(jsonArray.get(i));
   }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
index 78e466f..e581161 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
@@ -14,63 +14,62 @@
  */
 package org.apache.geode.management.internal.cli.json;
 
+import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 /**
- * Wrapper over JSONObject.
- *
- *
- * @since GemFire 7.0
+ * Simiulation of org.json.JSONObject based on Jackson Databind
  */
-public class GfJsonObject {
-  public static final Object NULL = JSONObject.NULL;
-
-  private JSONObject jsonObject;
-
-  public GfJsonObject() {
-    this.jsonObject = new JSONObject();
-  }
-
-  @SuppressWarnings("rawtypes")
-  public GfJsonObject(Object bean, boolean checkCyclicDep) {
-    if (checkCyclicDep) {
-      JSONObject.cyclicDepChkEnabled.set(true);
-      JSONObject.cyclicDependencySet.set(new HashSet());
+public class GfJsonObject extends AbstractJSONFormatter {
+  @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+  public static final Object NULL = new Object() {
+    @Override
+    public boolean equals(Object o) {
+      if (Objects.isNull(o)) {
+        return true;
+      }
+      return o == this;
     }
-    if (bean instanceof JSONObject) {
-      this.jsonObject = (JSONObject) bean;
-    } else {
-      this.jsonObject = new JSONObject(bean);
+
+    @Override
+    public int hashCode() {
+      return 0;
     }
-    if (checkCyclicDep) {
-      JSONObject.cyclicDepChkEnabled.set(false);
-      JSONObject.cyclicDependencySet.set(null);
+
+    @Override
+    public String toString() {
+      return "null";
     }
-  }
+  };
 
-  public GfJsonObject(GfJsonObject gfJsonObject) {
-    this.jsonObject = gfJsonObject.jsonObject;
+  private ObjectNode rootNode;
+
+  public GfJsonObject() {
+    super(-1, -1, false);
+    this.rootNode = mapper.createObjectNode();
   }
 
   public GfJsonObject(Map<?, ?> map) {
-    this.jsonObject = new JSONObject(map);
+    super(-1, -1, false);
+    this.rootNode = mapper.valueToTree(map);
   }
 
   public GfJsonObject(Object bean) {
-    if (bean instanceof JSONObject) {
-      this.jsonObject = (JSONObject) bean;
+    super(-1, -1, false);
+    if (bean instanceof ObjectNode) {
+      this.rootNode = (ObjectNode) bean;
     } else {
-      this.jsonObject = new JSONObject(bean);
+      this.rootNode = mapper.valueToTree(bean);
     }
   }
 
@@ -80,11 +79,20 @@ public class GfJsonObject {
    * @throws GfJsonException - If there is a syntax error in the source string or a duplicated key.
    */
   public GfJsonObject(String source) throws GfJsonException {
+    super(-1, -1, false);
     try {
-      this.jsonObject = new JSONObject(source);
-    } catch (JSONException e) {
+      this.rootNode = (ObjectNode) mapper.readTree(source);
+    } catch (IOException e) {
       throw new GfJsonException(e.getMessage());
     }
+    if (rootNode == null) {
+      throw new GfJsonException("Unable to parse JSON document");
+    }
+  }
+
+  void postCreateMapper() {
+    mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+    mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
   }
 
   /**
@@ -94,14 +102,16 @@ public class GfJsonObject {
    */
   public GfJsonObject accumulate(String key, Object value) throws GfJsonException {
     try {
-      if (jsonObject.has(key)) {
-        jsonObject.append(key, value);
+      if (rootNode.has(key)) {
+        append(key, value);
       } else {
         // first time always add JSONArray for accumulate - for convenience
-        jsonObject.put(key, new JSONArray().put(value));
+        ArrayNode array = mapper.createArrayNode();
+        array.add(mapper.valueToTree(value));
+        rootNode.set(key, array);
       }
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+    } catch (RuntimeException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
@@ -114,52 +124,67 @@ public class GfJsonObject {
    */
   public GfJsonObject append(String key, Object value) throws GfJsonException {
     try {
-      jsonObject.append(key, value);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      JsonNode current = rootNode.get(key);
+      if (current instanceof ArrayNode) {
+        ArrayNode array = (ArrayNode) current;
+        array.add(mapper.valueToTree(value));
+      } else if (current == null) {
+        ArrayNode array = mapper.createArrayNode();
+        array.add(mapper.valueToTree(value));
+        rootNode.set(key, array);
+      } else {
+        throw new GfJsonException("Cannot append to a non-array field");
+      }
+    } catch (RuntimeException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
 
-  public Object get(String key) {
-    return jsonObject.opt(key);
+  /**
+   * return the Jackson JsonNode associated with the given key
+   */
+  public JsonNode get(String key) {
+    return rootNode.get(key);
   }
 
   public String getString(String key) {
-    return jsonObject.optString(key);
+    JsonNode node = rootNode.get(key);
+    if (node == null) {
+      return null; // "null";
+    }
+    if (node.textValue() != null) {
+      return node.textValue();
+    }
+    return node.toString();
   }
 
   public int getInt(String key) {
-    return jsonObject.optInt(key);
+    return rootNode.get(key).asInt();
   }
 
   public long getLong(String key) {
-    return jsonObject.optLong(key);
+    return rootNode.get(key).asLong();
   }
 
   public double getDouble(String key) {
-    return jsonObject.optDouble(key);
+    return rootNode.get(key).asDouble();
   }
 
   public boolean getBoolean(String key) {
-    return jsonObject.optBoolean(key);
+    return rootNode.get(key).asBoolean();
   }
 
   public GfJsonObject getJSONObject(String key) {
-    Object opt = jsonObject.opt(key);
-    if (opt instanceof GfJsonObject) {
-      return (GfJsonObject) opt;
-    }
-
-    if (opt == null) {
+    Object value = rootNode.get(key);
+    if (value == null) {
       return null;
     }
-
-    return new GfJsonObject(opt);
+    return new GfJsonObject(value);
   }
 
-  public JSONObject getInternalJsonObject() {
-    return jsonObject;
+  public JsonNode getInternalJsonObject() {
+    return rootNode;
   }
 
   /**
@@ -168,11 +193,20 @@ public class GfJsonObject {
    * @throws GfJsonException If there is a syntax error while preparing GfJsonArray.
    */
   public GfJsonArray getJSONArray(String key) throws GfJsonException {
-    JSONArray jsonArray = jsonObject.optJSONArray(key);
-    if (jsonArray == null) {
+    JsonNode node = rootNode.get(key);
+    if (node == null) {
       return null;
     }
-    return new GfJsonArray(jsonArray);
+    if (!(node instanceof ArrayNode)) {
+      // convert from list format to array format
+      ArrayNode newNode = mapper.createArrayNode();
+      for (int i = 0; i < node.size(); i++) {
+        newNode.add(node.get("" + i));
+      }
+      rootNode.set(key, newNode);
+      return new GfJsonArray(newNode);
+    }
+    return new GfJsonArray(node);
   }
 
   /**
@@ -181,13 +215,17 @@ public class GfJsonObject {
    * @throws GfJsonException If there is a syntax error while preparing GfJsonArray.
    */
   public GfJsonArray names() throws GfJsonException {
-    GfJsonArray gfJsonArray = new GfJsonArray();
-    JSONArray names = jsonObject.names();
-    if (names != null) {
-      gfJsonArray = new GfJsonArray(names);
+    int size = rootNode.size();
+    if (size == 0) {
+      return new GfJsonArray();
     }
-
-    return gfJsonArray;
+    String[] fieldNames = new String[rootNode.size()];
+    Iterator<String> fieldNameIter = rootNode.fieldNames();
+    int i = 0;
+    while (fieldNameIter.hasNext()) {
+      fieldNames[i++] = fieldNameIter.next();
+    }
+    return new GfJsonArray(fieldNames);
   }
 
   /**
@@ -197,23 +235,19 @@ public class GfJsonObject {
    */
   public GfJsonObject put(String key, Object value) throws GfJsonException {
     try {
-      jsonObject.put(key, extractInternalForGfJsonOrReturnSame(value));
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      rootNode.set(key, toJsonNode(value));
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
 
   public GfJsonObject putAsJSONObject(String key, Object value) throws GfJsonException {
     try {
-      Object internalJsonObj = extractInternalForGfJsonOrReturnSame(value);
-      if (internalJsonObj == value) {
-        GfJsonObject jsonObj = new GfJsonObject(value);
-        internalJsonObj = jsonObj.getInternalJsonObject();
-      }
-      jsonObject.put(key, internalJsonObj);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      JsonNode internalJsonObj = toJsonNode(value);
+      rootNode.set(key, internalJsonObj);
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
@@ -224,115 +258,117 @@ public class GfJsonObject {
    * @throws GfJsonException If the value is a non-finite number.
    */
   public GfJsonObject putOpt(String key, Object value) throws GfJsonException {
-    try {
-      jsonObject.putOpt(key, extractInternalForGfJsonOrReturnSame(value));
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
-    }
-    return this;
-  }
-
-  /**
-   *
-   * @return this GfJsonObject
-   * @throws GfJsonException If the value is a non-finite number.
-   */
-  public GfJsonObject put(String key, Collection<?> value) throws GfJsonException {
-    try {
-      jsonObject.putOpt(key, value);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
-    }
-    return this;
-  }
-
-  public GfJsonObject putJSONArray(String key, GfJsonArray value) throws GfJsonException {
-    try {
-      jsonObject.putOpt(key, value.getInternalJsonArray());
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+    if (key == null || value == null) {
+      return this;
     }
-    return this;
-  }
-
-  public GfJsonObject put(String key, Map<?, ?> value) throws GfJsonException {
     try {
-      jsonObject.put(key, value);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      rootNode.set(key, toJsonNode(value));
+    } catch (IllegalArgumentException e) {
+      throw new GfJsonException(e);
     }
     return this;
   }
 
-  public static String quote(String string) {
-    return JSONObject.quote(string);
-  }
-
-  public Object remove(String key) {
-    return jsonObject.remove(key);
-  }
+  // /**
+  // *
+  // * @return this GfJsonObject
+  // * @throws GfJsonException If the value is a non-finite number.
+  // */
+  // public GfJsonObject put(String key, Collection<?> value) throws GfJsonException {
+  // if (key == null || value == null) {
+  // return this;
+  // }
+  // try {
+  // rootNode.set(key, toJsonNode(value));
+  // } catch (IllegalArgumentException e) {
+  // throw new GfJsonException(e);
+  // }
+  // return this;
+  // }
+  //
+  // public GfJsonObject put(String key, Map<?, ?> value) throws GfJsonException {
+  // try {
+  // rootNode.set(key, toJsonNode(value));
+  // } catch (IllegalArgumentException e) {
+  // throw new GfJsonException(e);
+  // }
+  // return this;
+  // }
+
+  // public static String quote(String string) {
+  // return JSONObject.quote(string);
+  // }
+
+  // public Object remove(String key) {
+  // return rootNode.remove(key);
+  // }
 
   public boolean has(String key) {
-    return jsonObject.has(key);
+    return rootNode.has(key);
   }
 
-  @SuppressWarnings("unchecked")
   public Iterator<String> keys() {
-    return jsonObject.keys();
+    return rootNode.fieldNames();
   }
 
   /**
    * @return the column size of this GfJsonObject
    */
   public int size() {
-    return jsonObject.length();
+    return rootNode.size();
   }
 
   public String toString() {
-    return jsonObject.toString();
+    return rootNode.toString();
   }
 
-  public String getType() {
-    return jsonObject.optString("type-class");
-  }
+  // public String getType() {
+  // return rootNode.optString("type-class");
+  // }
 
   /**
    *
    * @return this GfJsonObject
    * @throws GfJsonException If the object contains an invalid number.
    */
-  public String toIndentedString(int indentFactor) throws GfJsonException {
+  public String toIndentedString() throws GfJsonException {
     try {
-      return jsonObject.toString(indentFactor);
-    } catch (JSONException e) {
-      throw new GfJsonException(e.getMessage());
+      return rootNode.toString();
+    } catch (Exception e) {
+      throw new GfJsonException(e);
     }
   }
 
   public List<String> getArrayValues(String key) {
     List<String> result = new ArrayList<>();
-    if (jsonObject.has(key)) {
-      JSONArray jsonArray = jsonObject.getJSONArray(key);
-
-      for (int i = 0; i < jsonArray.length(); i++) {
-        result.add(jsonArray.getString(i));
+    if (rootNode.has(key)) {
+      JsonNode node = rootNode.get(key);
+      if (!(node instanceof ArrayNode)) {
+        throw new IllegalStateException("requested field is not an array: " + key);
+      }
+      ArrayNode array = (ArrayNode) node;
+      for (int i = 0; i < array.size(); i++) {
+        JsonNode valueNode = array.get(i);
+        result.add(valueNode.textValue() == null ? valueNode.toString() : valueNode.asText());
       }
     }
-
     return result;
   }
 
-  private static Object extractInternalForGfJsonOrReturnSame(Object value) {
-    Object returnedValue = value;
+  private JsonNode toJsonNode(Object value) {
+    if (value instanceof JsonNode) {
+      return (JsonNode) value;
+    }
     if (value instanceof GfJsonObject) {
-      returnedValue = ((GfJsonObject) value).getInternalJsonObject();
-    } else if (value instanceof GfJsonArray) {
-      returnedValue = ((GfJsonArray) value).getInternalJsonArray();
-    } else if (value == null) {
-      returnedValue = NULL;
+      return ((GfJsonObject) value).getInternalJsonObject();
     }
-
-    return returnedValue;
+    if (value instanceof GfJsonArray) {
+      return ((GfJsonArray) value).getInternalJsonArray();
+    }
+    if (value == null) {
+      return mapper.valueToTree(NULL);
+    }
+    return mapper.valueToTree(value);
   }
 
   public static GfJsonObject getGfJsonErrorObject(String errorMessage) {
@@ -341,8 +377,4 @@ public class GfJsonObject {
     return new GfJsonObject(errorMap);
   }
 
-  public static boolean isJSONKind(Object object) {
-    return object instanceof JSONObject;
-  }
-
 }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java
index 1720902..7a67e9c 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java
@@ -18,38 +18,15 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.core.type.WritableTypeId;
-import com.fasterxml.jackson.databind.BeanDescription;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationConfig;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
-
-import org.apache.geode.cache.Region;
-import org.apache.geode.cache.query.internal.StructImpl;
-import org.apache.geode.pdx.PdxInstance;
-
 /**
  * A JSON serializer that has special handling for collections to limit the number of elements
  * written to the document. It also has special handling for PdxInstance and query Structs.
  */
-public class QueryResultFormatter {
-
-  private final ObjectMapper mapper;
+public class QueryResultFormatter extends AbstractJSONFormatter {
 
   /**
    * map contains the named objects to be serialized
@@ -57,12 +34,6 @@ public class QueryResultFormatter {
   private final Map<String, List<Object>> map;
 
   /**
-   * serializedObjects is used to prevent recursive serialization in cases where
-   * there are cyclical references
-   */
-  private final Map<Object, Object> serializedObjects;
-
-  /**
    * Create a formatter that will limit collection sizes to maxCollectionElements
    * and will limit object traversal to being the same but in depth.
    *
@@ -78,35 +49,9 @@ public class QueryResultFormatter {
    * @param maxCollectionElements limit on collection elements
    * @param serializationDepth when traversing objects, how deep should we go?
    */
-  private QueryResultFormatter(int maxCollectionElements, int serializationDepth) {
+  public QueryResultFormatter(int maxCollectionElements, int serializationDepth) {
+    super(maxCollectionElements, serializationDepth, true);
     this.map = new LinkedHashMap<>();
-
-    this.serializedObjects = new IdentityHashMap<>();
-    this.mapper = new ObjectMapper();
-
-    SimpleModule mapperModule =
-        new PreventReserializationModule(serializedObjects, serializationDepth);
-
-    // insert a collection serializer that limits the number of elements generated
-    mapperModule.addSerializer(Collection.class, new CollectionSerializer(maxCollectionElements));
-    // insert a PdxInstance serializer that knows about PDX fields/values
-    mapperModule.addSerializer(PdxInstance.class, new PdxInstanceSerializer());
-    // insert a Struct serializer that knows about its format
-    mapperModule.addSerializer(StructImpl.class, new StructSerializer());
-    // insert a RegionEntry serializer because they're too messy looking
-    mapperModule.addSerializer(Region.Entry.class, new RegionEntrySerializer());
-
-    mapper.registerModule(mapperModule);
-
-    // allow objects with no content
-    mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
-    // use toString on Enums
-    mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
-    // sort fields alphabetically
-    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
-    // add type information (Jackson has no way to force it to do this for all values)
-    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
-
   }
 
   /**
@@ -184,233 +129,4 @@ public class QueryResultFormatter {
   }
 
 
-  private static class PreventReserializationSerializer extends JsonSerializer {
-
-    private JsonSerializer defaultSerializer;
-    Map<Object, Object> serializedObjects;
-    private final int serializationDepth;
-    int depth;
-
-    PreventReserializationSerializer(JsonSerializer serializer, Map serializedObjects,
-        int serializationDepth) {
-      defaultSerializer = serializer;
-      this.serializedObjects = serializedObjects;
-      this.serializationDepth = serializationDepth;
-    }
-
-    boolean isPrimitiveOrWrapper(Class<?> klass) {
-      return klass.isAssignableFrom(Byte.class) || klass.isAssignableFrom(byte.class)
-          || klass.isAssignableFrom(Short.class) || klass.isAssignableFrom(short.class)
-          || klass.isAssignableFrom(Integer.class) || klass.isAssignableFrom(int.class)
-          || klass.isAssignableFrom(Long.class) || klass.isAssignableFrom(long.class)
-          || klass.isAssignableFrom(Float.class) || klass.isAssignableFrom(float.class)
-          || klass.isAssignableFrom(Double.class) || klass.isAssignableFrom(double.class)
-          || klass.isAssignableFrom(Boolean.class) || klass.isAssignableFrom(boolean.class)
-          || klass.isAssignableFrom(String.class) || klass.isAssignableFrom(char.class)
-          || klass.isAssignableFrom(Character.class) || klass.isAssignableFrom(java.sql.Date.class)
-          || klass.isAssignableFrom(java.util.Date.class)
-          || klass.isAssignableFrom(java.math.BigDecimal.class);
-    }
-
-    @Override
-    public void serializeWithType(Object value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      if (value == null || isPrimitiveOrWrapper(value.getClass())) {
-        defaultSerializer.serializeWithType(value, gen, serializers, typeSer);
-        return;
-      }
-      depth += 1;
-      try {
-        if (depth > serializationDepth) {
-          gen.writeString("{}");
-        } else if (serializedObjects.containsKey(value)) {
-          gen.writeString("duplicate " + value.getClass().getName());
-        } else {
-          serializedObjects.put(value, value);
-          defaultSerializer.serializeWithType(value, gen, serializers, typeSer);
-        }
-      } finally {
-        depth--;
-      }
-    }
-
-    @Override
-    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers)
-        throws IOException {
-      if (value == null || isPrimitiveOrWrapper(value.getClass())) {
-        defaultSerializer.serialize(value, gen, serializers);
-        return;
-      }
-      if (serializedObjects.containsKey(value)) {
-        gen.writeStartObject(value);
-        gen.writeFieldName("duplicate");
-        gen.writeString("reference@" + Integer.toHexString(System.identityHashCode(value)));
-        gen.writeEndObject();
-      } else {
-        serializedObjects.put(value, value);
-        defaultSerializer.serialize(value, gen, serializers);
-      }
-    }
-  }
-
-
-  private static class CollectionSerializer extends JsonSerializer<Collection> {
-    private final int maxCollectionElements;
-
-    public CollectionSerializer(int maxCollectionElements) {
-      this.maxCollectionElements = maxCollectionElements;
-    }
-
-    @Override
-    public void serializeWithType(Collection value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      gen.setCurrentValue(value);
-      WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
-          typeSer.typeId(value, JsonToken.START_OBJECT));
-      _serialize(value, gen);
-      typeSer.writeTypeSuffix(gen, typeIdDef);
-    }
-
-    @Override
-    public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers)
-        throws IOException {
-      gen.writeStartObject();
-      _serialize(value, gen);
-      gen.writeEndObject();
-    }
-
-    void _serialize(Collection value, JsonGenerator gen) throws IOException {
-      Iterator<Object> objects = value.iterator();
-      for (int i = 0; i < maxCollectionElements && objects.hasNext(); i++) {
-        Object nextObject = objects.next();
-        gen.writeObjectField("" + i, nextObject);
-      }
-    }
-
-    @Override
-    public Class<Collection> handledType() {
-      return Collection.class;
-    }
-  }
-
-
-  private static class PdxInstanceSerializer extends JsonSerializer<PdxInstance> {
-    @Override
-    public void serializeWithType(PdxInstance value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      WritableTypeId writableTypeId = typeSer.typeId(value, JsonToken.START_OBJECT);
-      typeSer.writeTypePrefix(gen, writableTypeId);
-      _serialize(value, gen);
-      typeSer.writeTypeSuffix(gen, writableTypeId);
-    }
-
-    @Override
-    public void serialize(PdxInstance value, JsonGenerator gen, SerializerProvider serializers)
-        throws IOException {
-      gen.writeStartObject();
-      _serialize(value, gen);
-      gen.writeEndObject();
-    }
-
-    void _serialize(PdxInstance value, JsonGenerator gen) throws IOException {
-      for (String field : value.getFieldNames()) {
-        gen.writeObjectField(field, value.getField(field));
-      }
-    }
-
-    @Override
-    public Class<PdxInstance> handledType() {
-      return PdxInstance.class;
-    }
-  }
-
-  private static class StructSerializer extends JsonSerializer<StructImpl> {
-    @Override
-    public void serializeWithType(StructImpl value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.START_OBJECT));
-      _serialize(value, gen);
-      typeSer.writeTypeSuffix(gen, typeSer.typeId(value, JsonToken.START_OBJECT));
-    }
-
-    @Override
-    public void serialize(StructImpl value, JsonGenerator gen, SerializerProvider serializers)
-        throws IOException {
-      gen.writeStartObject();
-      _serialize(value, gen);
-      gen.writeEndObject();
-    }
-
-    void _serialize(StructImpl value, JsonGenerator gen) throws IOException {
-      String[] fields = value.getFieldNames();
-      Object[] values = value.getFieldValues();
-      for (int i = 0; i < fields.length; i++) {
-        gen.writeObjectField(fields[i], values[i]);
-      }
-    }
-
-    @Override
-    public Class<StructImpl> handledType() {
-      return StructImpl.class;
-    }
-  }
-
-  private static class RegionEntrySerializer extends JsonSerializer<Region.Entry> {
-    @Override
-    public void serializeWithType(Region.Entry value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.START_OBJECT));
-      gen.writeObjectField(value.getKey().toString(), value.getValue());
-      typeSer.writeTypeSuffix(gen, typeSer.typeId(value, JsonToken.START_OBJECT));
-    }
-
-    @Override
-    public void serialize(Region.Entry value, JsonGenerator gen, SerializerProvider serializers)
-        throws IOException {
-      gen.writeStartObject();
-      gen.writeObjectField(value.getKey().toString(), value.getValue());
-      gen.writeEndObject();
-    }
-
-    @Override
-    public Class<Region.Entry> handledType() {
-      return Region.Entry.class;
-    }
-  }
-
-  /**
-   * A Jackson module that installs a serializer-modifier to detect and prevent
-   * reserialization of objects that have already been serialized. W/o this
-   * Jackson would throw infinite-recursion exceptions.
-   */
-  private static class PreventReserializationModule extends SimpleModule {
-    private final Map<Object, Object> serializedObjects;
-    private final int serializationDepth;
-
-    PreventReserializationModule(Map<Object, Object> serializedObjects, int serializationDepth) {
-      this.serializedObjects = serializedObjects;
-      this.serializationDepth = serializationDepth;
-    }
-
-    @Override
-    public void setupModule(SetupContext context) {
-      // install a modifier that prevents recursive serialization in cases where
-      // there are cyclical references
-      super.setupModule(context);
-      context.addBeanSerializerModifier(new BeanSerializerModifier() {
-        @Override
-        public JsonSerializer<?> modifySerializer(
-            SerializationConfig config, BeanDescription desc, JsonSerializer<?> serializer) {
-          return new PreventReserializationSerializer(serializer, serializedObjects,
-              serializationDepth);
-        }
-      });
-    }
-
-  }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
index d297b45..1164494 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
@@ -171,7 +171,7 @@ public abstract class AbstractResultData implements ResultData {
     int length = byteDataArray.size();
     String options = length > 1 ? "(y/N/a)" : "(y/N)";
     for (int i = 0; i < length; i++) {
-      GfJsonObject object = byteDataArray.getJSONObject(i);
+      GfJsonObject object = byteDataArray.getInternalJsonObject(i);
 
       int fileType = object.getInt(FILE_TYPE_FIELD);
 
@@ -187,7 +187,7 @@ public abstract class AbstractResultData implements ResultData {
         fileNameBytes = GfJsonArray.toByteArray(fileNameJsonBytes);
         fileName = new String(fileNameBytes);
       } else { // if on member
-        fileName = (String) object.get(FILE_NAME_FIELD);
+        fileName = object.getString(FILE_NAME_FIELD);
       }
 
       // build file message
@@ -198,11 +198,11 @@ public abstract class AbstractResultData implements ResultData {
         fileMessageBytes = GfJsonArray.toByteArray(fileMessageJsonBytes);
         fileMessage = new String(fileMessageBytes);
       } else { // if on member
-        fileMessage = (String) object.get(FILE_MESSAGE);
+        fileMessage = object.getString(FILE_MESSAGE);
       }
 
-      String fileDataString = (String) object.get(FILE_DATA_FIELD);
-      int fileDataLength = (int) object.get(DATA_LENGTH_FIELD);
+      String fileDataString = object.getString(FILE_DATA_FIELD);
+      int fileDataLength = object.getInt(DATA_LENGTH_FIELD);
       byte[] byteArray = Base64.getDecoder().decode(fileDataString);
       byte[] uncompressBytes = CliUtil.uncompressBytes(byteArray, fileDataLength).getData();
 
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
index c92024d..bccd5cf 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
@@ -16,7 +16,6 @@ package org.apache.geode.management.internal.cli.result;
 
 import java.util.Iterator;
 
-import org.apache.geode.management.internal.cli.json.GfJsonArray;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 
@@ -227,20 +226,6 @@ public class CompositeResultData extends AbstractResultData {
       return tabularResultData;
     }
 
-    public Object retrieveObject(String name) {
-      Object retrievedObject = sectionGfJsonObject.get(name);
-
-      if (retrievedObject instanceof GfJsonArray) {
-        GfJsonArray.toStringArray(((GfJsonArray) retrievedObject));
-      }
-
-      return sectionGfJsonObject.get(name);
-    }
-
-    public String retrieveString(String name) {
-      return sectionGfJsonObject.getString(name);
-    }
-
     public static String generateSectionKey(String keyToRetrieve) {
       return SECTION_DATA_ACCESSOR + "-" + keyToRetrieve;
     }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ErrorResultData.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ErrorResultData.java
index c9cbf57..ea31ee1 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ErrorResultData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ErrorResultData.java
@@ -14,6 +14,8 @@
  */
 package org.apache.geode.management.internal.cli.result;
 
+import com.fasterxml.jackson.databind.JsonNode;
+
 import org.apache.geode.management.cli.Result.Status;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
@@ -40,11 +42,11 @@ public class ErrorResultData extends InfoResultData {
   }
 
   public int getErrorCode() {
-    Integer code = (Integer) contentObject.get(ERROR_CODE);
+    JsonNode code = contentObject.get(ERROR_CODE);
     if (code == null) {
       return ResultBuilder.ERRORCODE_DEFAULT;
     }
-    return code;
+    return code.asInt();
   }
 
   /**
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
index d9493dd..9c9b29e 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
@@ -25,9 +25,9 @@ import java.util.Vector;
 import java.util.stream.Collectors;
 import java.util.zip.DataFormatException;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import org.apache.logging.log4j.Logger;
-import org.json.JSONArray;
-import org.json.JSONObject;
 
 import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.management.internal.cli.GfshParser;
@@ -262,7 +262,7 @@ public class LegacyCommandResult implements CommandResult {
   }
 
   private static String[] getValuesSeparatedByLines(Object object) {
-    String valueString = String.valueOf(object);
+    String valueString = "" + object;
     return valueString.split(GfshParser.LINE_SEPARATOR);
   }
 
@@ -275,7 +275,7 @@ public class LegacyCommandResult implements CommandResult {
 
     // build Table Header first
     for (int i = 0; i < numOfColumns; i++) {
-      Object object = columnNames.get(i);
+      Object object = columnNames.getString(i);
       if (ResultData.BYTE_DATA_ACCESSOR.equals(object)) {
         // skip file data if any
         continue;
@@ -286,7 +286,7 @@ public class LegacyCommandResult implements CommandResult {
     // Build remaining rows by extracting data column-wise from JSON object
     Row[] dataRows = null;
     for (int i = 0; i < numOfColumns; i++) {
-      Object object = columnNames.get(i);
+      Object object = columnNames.getString(i);
       if (ResultData.BYTE_DATA_ACCESSOR.equals(object)) {
         // skip file data if any
         continue;
@@ -312,7 +312,7 @@ public class LegacyCommandResult implements CommandResult {
 
     // Add data column-wise
     for (int j = 0; j < size; j++) {
-      dataRows[j].newLeftCol(accumulatedData.get(j));
+      dataRows[j].newLeftCol(accumulatedData.getString(j));
     }
     return dataRows;
   }
@@ -426,16 +426,18 @@ public class LegacyCommandResult implements CommandResult {
 
   @Override
   public List<String> getColumnFromTableContent(String column, String sectionId, String tableId) {
-    return toList(getTableContent(sectionId, tableId).getInternalJsonObject().getJSONArray(column));
+    return toList((ArrayNode) getTableContent(sectionId, tableId).get(column));
   }
 
   @Override
   public Map<String, List<String>> getMapFromTableContent(String sectionId, String tableId) {
     Map<String, List<String>> result = new LinkedHashMap<>();
 
-    JSONObject table = getTableContent(sectionId, tableId).getInternalJsonObject();
-    for (String column : table.keySet()) {
-      result.put(column, toList(table.getJSONArray(column)));
+    JsonNode table = getTableContent(sectionId, tableId).getInternalJsonObject();
+    Iterator<String> fieldNames = table.fieldNames();
+    while (fieldNames.hasNext()) {
+      String column = fieldNames.next();
+      result.put(column, toList((ArrayNode) table.get(column)));
     }
 
     return result;
@@ -526,11 +528,11 @@ public class LegacyCommandResult implements CommandResult {
     return getTableContent("0", "0").getArrayValues(columnName);
   }
 
-  private List<String> toList(JSONArray array) {
-    Object[] values = new Object[array.length()];
+  private List<String> toList(ArrayNode array) {
+    Object[] values = new Object[array.size()];
 
-    for (int i = 0; i < array.length(); i++) {
-      values[i] = array.get(i);
+    for (int i = 0; i < array.size(); i++) {
+      values[i] = array.get(i).textValue();
     }
 
     return Arrays.stream(values).map(Object::toString).collect(Collectors.toList());
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultBuilder.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultBuilder.java
index 8067360..8f1feea 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultBuilder.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultBuilder.java
@@ -258,7 +258,7 @@ public class ResultBuilder {
         resultData = errorResultData;
       }
 
-      Integer statusCode = (Integer) jsonObject.get("status");
+      Integer statusCode = jsonObject.getInt("status");
       if (Result.Status.OK.getCode() == statusCode) {
         resultData.setStatus(Result.Status.OK);
       } else {
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
index 94cf9ed..e79da62 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
@@ -14,6 +14,8 @@
  */
 package org.apache.geode.management.internal.cli.result;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import org.apache.geode.management.cli.Result.Status;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 
@@ -46,21 +48,25 @@ public interface ResultData {
 
   String getFooter();
 
+  @JsonIgnore
   default GfJsonObject getGfJsonObject() {
     throw new UnsupportedOperationException(
         "This should never be called and only exists during migration from GfJsonObject to POJOs - use getContent() instead");
   }
 
+  @JsonIgnore
   default String getType() {
     throw new UnsupportedOperationException(
         "This should never be called and only exists during migration from GfJsonObject to POJOs");
   }
 
+  @JsonIgnore
   default Status getStatus() {
     throw new UnsupportedOperationException(
         "This should never be called and only exists during migration from GfJsonObject to POJOs");
   }
 
+  @JsonIgnore
   default void setStatus(final Status status) {
     throw new UnsupportedOperationException(
         "This should never be called and only exists during migration from GfJsonObject to POJOs");
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
index c18b892..736e60f 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
@@ -119,7 +119,7 @@ public class TabularResultData extends AbstractResultData {
       GfJsonArray jsonArray = contentObject.getJSONArray(columnName);
       int size = jsonArray.size();
       for (int i = 0; i < size; i++) {
-        values.add(String.valueOf(jsonArray.get(i)));
+        values.add(String.valueOf(jsonArray.getString(i)));
       }
     } catch (GfJsonException e) {
       throw new ResultDataException(e.getMessage());
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java
index 6e6e2d8..3fbee6c 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java
@@ -706,7 +706,8 @@ public class Gfsh extends JLineShell {
           if (!isScriptRunning) {
             // Normal Command
             while (commandResult.hasNextLine()) {
-              write(commandResult.nextLine(), isError);
+              String nextLine = commandResult.nextLine();
+              write(nextLine, isError);
             }
           } else if (!suppressScriptCmdOutput) {
             // Command is part of script. Show output only when quite=false
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/JsonUtil.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/JsonUtil.java
index 24c9dee..7af37f0 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/JsonUtil.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/JsonUtil.java
@@ -24,18 +24,15 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.commons.beanutils.ConvertUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
 
-import org.apache.geode.internal.ClassPathLoader;
-import org.apache.geode.management.internal.cli.json.GfJsonArray;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
-import org.apache.geode.management.internal.cli.result.ResultDataException;
 
 /**
  * This class contains utility methods for JSON (http://www.json.org/) which is used by classes used
@@ -47,93 +44,6 @@ import org.apache.geode.management.internal.cli.result.ResultDataException;
 public class JsonUtil {
 
   /**
-   * Converts given JSON String in to a Map. Refer http://www.json.org/ to construct a JSON format.
-   *
-   * @param jsonString jsonString to be converted in to a Map.
-   * @return a Map created from
-   *
-   * @throws IllegalArgumentException if the specified JSON string can not be converted in to a Map
-   */
-  public static Map<String, String> jsonToMap(String jsonString) {
-    Map<String, String> jsonMap = new TreeMap<String, String>();
-    try {
-      GfJsonObject jsonObject = new GfJsonObject(jsonString);
-      Iterator<String> keys = jsonObject.keys();
-
-      while (keys.hasNext()) {
-        String key = keys.next();
-        jsonMap.put(key, jsonObject.getString(key));
-      }
-
-    } catch (GfJsonException e) {
-      throw new IllegalArgumentException(
-          "Could not convert jsonString : '" + jsonString + "' to map.");
-    }
-    return jsonMap;
-  }
-
-  /**
-   * Converts given Map in to a JSON string representing a Map. Refer http://www.json.org/ for more.
-   *
-   * @param properties a Map of Strings to be converted in to JSON String
-   * @return a JSON string representing the specified Map.
-   */
-  public static String mapToJson(Map<String, String> properties) {
-    return new GfJsonObject(properties).toString();
-  }
-
-  /**
-   * Converts given Object in to a JSON string representing an Object. Refer http://www.json.org/
-   * for more.
-   *
-   * @param object an Object to be converted in to JSON String
-   * @return a JSON string representing the specified object.
-   */
-  public static String objectToJson(Object object) {
-    return new GfJsonObject(object).toString();
-  }
-
-  /**
-   * Converts given Object in to a JSON string representing an Object. If object contains an
-   * attribute which itself is another object it will be displayed as className if its json
-   * representation exceeds the length
-   *
-   * @param object an Object to be converted in to JSON String
-   * @return a JSON string representing the specified object.
-   */
-  public static String objectToJsonNested(Object object, int length) {
-    return objectToJsonNestedChkCDep(object, length, false);
-  }
-
-  public static String objectToJsonNestedChkCDep(Object object, int length) {
-    return objectToJsonNestedChkCDep(object, length, true);
-  }
-
-  private static String objectToJsonNestedChkCDep(Object object, int length,
-      boolean checkCyclicDep) {
-    GfJsonObject jsonObject = new GfJsonObject(object, checkCyclicDep);
-    Iterator<String> iterator = jsonObject.keys();
-    while (iterator.hasNext()) {
-      String key = iterator.next();
-      Object value = jsonObject.get(key);
-      if (value != null && !isPrimitiveOrWrapper(value.getClass())) {
-        GfJsonObject jsonified = new GfJsonObject(value);
-        String stringified = jsonified.toString();
-        try {
-          if (stringified.length() > length) {
-            jsonObject.put(key, jsonified.getType());
-          } else {
-            jsonObject.put(key, stringified);
-          }
-        } catch (GfJsonException e) {
-          e.printStackTrace();
-        }
-      }
-    }
-    return jsonObject.toString();
-  }
-
-  /**
    * Converts given JSON String in to a Object. Refer http://www.json.org/ to construct a JSON
    * format.
    *
@@ -199,33 +109,67 @@ public class JsonUtil {
       throw new IllegalArgumentException("Couldn't convert JSON to Object of type " + klass, e);
     } catch (IllegalAccessException e) {
       throw new IllegalArgumentException("Couldn't convert JSON to Object of type " + klass, e);
-    } catch (GfJsonException e) {
-      throw new IllegalArgumentException("Couldn't convert JSON to Object of type " + klass, e);
     } catch (IllegalArgumentException e) {
       throw new IllegalArgumentException("Couldn't convert JSON to Object of type " + klass, e);
     } catch (InvocationTargetException e) {
       throw new IllegalArgumentException("Couldn't convert JSON to Object of type " + klass, e);
+    } catch (GfJsonException e) {
+      throw new IllegalArgumentException(e);
     }
     return objectFromJson;
   }
 
+  private static void throwUnsupportedType(String containerType, JsonNodeType valueType)
+      throws GfJsonException {
+    throw new GfJsonException(String.format(
+        "Only primitive types are supported in %s type for input commands but found %s",
+        containerType, valueType.toString()));
+  }
+
   private static Object toArray(Object value, Class<?> parameterType) throws GfJsonException {
     Class arrayComponentType = parameterType.getComponentType();
     if (isPrimitiveOrWrapper(arrayComponentType)) {
-      if (value instanceof JSONArray) {
+      if (value instanceof ArrayNode) {
         try {
-          JSONArray jsonArray = (JSONArray) value;
-          Object jArray = Array.newInstance(arrayComponentType, jsonArray.length());
-          for (int i = 0; i < jsonArray.length(); i++) {
-            Array.set(jArray, i, jsonArray.get(i));
+          ArrayNode jsonArray = (ArrayNode) value;
+          Object jArray = Array.newInstance(arrayComponentType, jsonArray.size());
+          for (int i = 0; i < jsonArray.size(); i++) {
+            JsonNode elem = jsonArray.get(i);
+            switch (elem.getNodeType()) {
+              case ARRAY:
+                throwUnsupportedType("array", elem.getNodeType());
+              case BINARY:
+                throwUnsupportedType("array", elem.getNodeType());
+              case BOOLEAN:
+                Array.set(jArray, i, jsonArray.get(i).booleanValue());
+              case MISSING:
+                throwUnsupportedType("array", elem.getNodeType());
+              case NULL:
+                throwUnsupportedType("array", elem.getNodeType());
+              case NUMBER:
+                if (elem.isIntegralNumber()) {
+                  Array.set(jArray, i, elem.longValue());
+                } else {
+                  Array.set(jArray, i, elem.doubleValue());
+                }
+                break;
+              case OBJECT:
+                throwUnsupportedType("array", elem.getNodeType());
+              case POJO:
+                throwUnsupportedType("array", elem.getNodeType());
+              case STRING:
+                if (elem.textValue() != null) {
+                  Array.set(jArray, i, elem.textValue());
+                } else {
+                  Array.set(jArray, i, elem.toString());
+                }
+            }
           }
           return jArray;
         } catch (ArrayIndexOutOfBoundsException e) {
           throw new GfJsonException(e);
         } catch (IllegalArgumentException e) {
           throw new GfJsonException(e);
-        } catch (JSONException e) {
-          throw new GfJsonException(e);
         }
       } else {
         throw new GfJsonException("Expected JSONArray for array type");
@@ -244,95 +188,136 @@ public class JsonUtil {
   @SuppressWarnings({"rawtypes", "unchecked"})
   private static Object toSet(Object value, Class<?> parameterType) throws GfJsonException {
     try {
-      JSONArray array = (JSONArray) value;
+      ArrayNode array = (ArrayNode) value;
       Set set = new HashSet();
-      for (int i = 0; i < array.length(); i++) {
-        Object element = array.get(i);
-        if (isPrimitiveOrWrapper(element.getClass())) {
-          set.add(element);
-        } else
-          throw new GfJsonException(
-              "Only primitive types are supported in set type for input commands");
+      for (int i = 0; i < array.size(); i++) {
+        JsonNode elem = array.get(i);
+        switch (elem.getNodeType()) {
+          case ARRAY:
+            throwUnsupportedType("list", elem.getNodeType());
+          case BINARY:
+            throwUnsupportedType("list", elem.getNodeType());
+          case BOOLEAN:
+            set.add(elem.booleanValue());
+          case MISSING:
+            throwUnsupportedType("list", elem.getNodeType());
+          case NULL:
+            throwUnsupportedType("list", elem.getNodeType());
+          case NUMBER:
+            if (elem.isIntegralNumber()) {
+              set.add(elem.longValue());
+            } else {
+              set.add(elem.doubleValue());
+            }
+            break;
+          case OBJECT:
+            throwUnsupportedType("list", elem.getNodeType());
+          case POJO:
+            throwUnsupportedType("list", elem.getNodeType());
+          case STRING:
+            if (elem.textValue() != null) {
+              set.add(elem.textValue());
+            } else {
+              set.add(elem.toString());
+            }
+        }
       }
       return set;
-    } catch (JSONException e) {
+    } catch (Exception e) {
       throw new GfJsonException(e);
     }
   }
 
   private static Object toMap(Object value, Class<?> parameterType) throws GfJsonException {
     try {
-      if (value instanceof JSONObject) {
-        JSONObject obj = (JSONObject) value;
-        Iterator iterator = obj.keys();
+      if (value instanceof ObjectNode) {
+        ObjectNode obj = (ObjectNode) value;
+        Iterator iterator = obj.fieldNames();
         Map map = new HashMap();
         while (iterator.hasNext()) {
           String key = (String) iterator.next();
-          Object elem;
-          elem = obj.get(key);
-          if (isPrimitiveOrWrapper(elem.getClass())) {
-            map.put(key, elem);
-          } else
-            throw new GfJsonException(
-                "Only primitive types are supported in map type for input commands");
+          JsonNode elem = obj.get(key);
+          switch (elem.getNodeType()) {
+            case ARRAY:
+              throwUnsupportedType("map", elem.getNodeType());
+            case BINARY:
+              throwUnsupportedType("map", elem.getNodeType());
+            case BOOLEAN:
+              map.put(key, elem.booleanValue());
+            case MISSING:
+              throwUnsupportedType("map", elem.getNodeType());
+            case NULL:
+              throwUnsupportedType("map", elem.getNodeType());
+            case NUMBER:
+              if (elem.isIntegralNumber()) {
+                map.put(key, elem.longValue());
+              } else {
+                map.put(key, elem.doubleValue());
+              }
+              break;
+            case OBJECT:
+              throwUnsupportedType("map", elem.getNodeType());
+            case POJO:
+              throwUnsupportedType("map", elem.getNodeType());
+            case STRING:
+              if (elem.textValue() != null) {
+                map.put(key, elem.textValue());
+              } else {
+                map.put(key, elem.toString());
+              }
+          }
         }
         return map;
       } else
         throw new GfJsonException(
             "Expected JSONObject for Map. Retrieved type is " + value.getClass());
-    } catch (JSONException e) {
+    } catch (Exception e) {
       throw new GfJsonException(e);
     }
   }
 
   private static Object toList(Object value, Class<?> parameterType) throws GfJsonException {
     try {
-      JSONArray array = (JSONArray) value;
+      ArrayNode array = (ArrayNode) value;
       List list = new ArrayList();
-      for (int i = 0; i < array.length(); i++) {
-        Object element = array.get(i);
-        if (isPrimitiveOrWrapper(element.getClass())) {
-          list.add(element);
-        } else
-          throw new GfJsonException(
-              "Only primitive types are supported in set type for input commands");
+      for (int i = 0; i < array.size(); i++) {
+        JsonNode elem = array.get(i);
+        switch (elem.getNodeType()) {
+          case ARRAY:
+            throwUnsupportedType("list", elem.getNodeType());
+          case BINARY:
+            throwUnsupportedType("list", elem.getNodeType());
+          case BOOLEAN:
+            list.add(elem.booleanValue());
+          case MISSING:
+            throwUnsupportedType("list", elem.getNodeType());
+          case NULL:
+            throwUnsupportedType("list", elem.getNodeType());
+          case NUMBER:
+            if (elem.isIntegralNumber()) {
+              list.add(elem.longValue());
+            } else {
+              list.add(elem.doubleValue());
+            }
+            break;
+          case OBJECT:
+            throwUnsupportedType("list", elem.getNodeType());
+          case POJO:
+            throwUnsupportedType("list", elem.getNodeType());
+          case STRING:
+            if (elem.textValue() != null) {
+              list.add(elem.textValue());
+            } else {
+              list.add(elem.toString());
+            }
+        }
       }
       return list;
-    } catch (JSONException e) {
+    } catch (Exception e) {
       throw new GfJsonException(e);
     }
   }
 
-  public static Object jsonToObject(String jsonString) {
-    Object objectFromJson = null;
-    try {
-      GfJsonObject jsonObject = new GfJsonObject(jsonString);
-
-      Iterator<String> keys = jsonObject.keys();
-
-      Object[] arr = new Object[jsonObject.size()];
-      int i = 0;
-
-      while (keys.hasNext()) {
-        String key = keys.next();
-        Class<?> klass = ClassPathLoader.getLatest().forName(key);
-        arr[i++] = jsonToObject((String) jsonObject.get(key).toString(), klass);
-      }
-
-      if (arr.length == 1) {
-        objectFromJson = arr[0];
-      } else {
-        objectFromJson = arr;
-      }
-    } catch (GfJsonException e) {
-      throw new IllegalArgumentException("Couldn't convert JSON to Object.", e);
-    } catch (ClassNotFoundException e) {
-      throw new IllegalArgumentException("Couldn't convert JSON to Object.", e);
-    }
-
-    return objectFromJson;
-  }
-
   public static String capitalize(String str) {
     String capitalized = str;
     if (str == null || str.isEmpty()) {
@@ -426,127 +411,4 @@ public class JsonUtil {
     }
     return value;
   }
-
-  public static int getInt(GfJsonObject jsonObject, String byName) {
-    return jsonObject.getInt(byName);
-  }
-
-  public static long getLong(GfJsonObject jsonObject, String byName) {
-    return jsonObject.getLong(byName);
-  }
-
-  public static double getDouble(GfJsonObject jsonObject, String byName) {
-    return jsonObject.getDouble(byName);
-  }
-
-  public static boolean getBoolean(GfJsonObject jsonObject, String byName) {
-    return jsonObject.getBoolean(byName);
-  }
-
-  public static String getString(GfJsonObject jsonObject, String byName) {
-    return jsonObject.getString(byName);
-  }
-
-  public static GfJsonObject getJSONObject(GfJsonObject jsonObject, String byName) {
-    return jsonObject.getJSONObject(byName);
-  }
-
-  public static String[] getStringArray(GfJsonObject jsonObject, String byName) {
-    String[] stringArray = null;
-    try {
-      GfJsonArray jsonArray = jsonObject.getJSONArray(byName);
-      stringArray = GfJsonArray.toStringArray(jsonArray);
-    } catch (GfJsonException e) {
-      throw new ResultDataException(e.getMessage());
-    }
-    return stringArray;
-  }
-
-  public static byte[] getByteArray(GfJsonObject jsonObject, String byName) {
-    byte[] byteArray = null;
-    try {
-      GfJsonArray jsonArray = jsonObject.getJSONArray(byName);
-      byteArray = GfJsonArray.toByteArray(jsonArray);
-    } catch (GfJsonException e) {
-      throw new ResultDataException(e.getMessage());
-    }
-    return byteArray;
-  }
-
-  // For testing purpose
-  public static void main(String[] args) {
-    System.out.println(capitalize("key"));
-    System.out.println(capitalize("Key"));
-
-    String str =
-        "{\"org.apache.geode.management.internal.cli.JsonUtil$Employee\":{\"id\":1234,\"name\":\"Foo BAR\",\"department\":{\"id\":456,\"name\":\"support\"}}}";
-    Object jsonToObject = jsonToObject(str);
-    System.out.println(jsonToObject);
-
-    str = "{\"id\":1234,\"name\":\"Foo BAR\",\"department\":{\"id\":456,\"name\":\"support\"}}";
-    Object jsonToObject2 = jsonToObject(str, Employee.class);
-    System.out.println(jsonToObject2);
-  }
-
-  public static class Employee {
-    private int id;
-    private String name;
-    private Department department;
-
-    public int getId() {
-      return id;
-    }
-
-    public void setId(int id) {
-      this.id = id;
-    }
-
-    public String getName() {
-      return name;
-    }
-
-    public void setName(String name) {
-      this.name = name;
-    }
-
-    public Department getDepartment() {
-      return department;
-    }
-
-    public void setDepartment(Department department) {
-      this.department = department;
-    }
-
-    @Override
-    public String toString() {
-      return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
-    }
-  }
-
-  public static class Department {
-    private int id;
-    private String name;
-
-    public int getId() {
-      return id;
-    }
-
-    public void setId(int id) {
-      this.id = id;
-    }
-
-    public String getName() {
-      return name;
-    }
-
-    public void setName(String name) {
-      this.name = name;
-    }
-
-    @Override
-    public String toString() {
-      return "Department [id=" + id + ", name=" + name + "]";
-    }
-  }
-
 }
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherServiceStateTest.java b/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherServiceStateTest.java
index da47ac7..07d0a36 100755
--- a/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherServiceStateTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/AbstractLauncherServiceStateTest.java
@@ -42,7 +42,6 @@ import org.junit.Test;
 
 import org.apache.geode.internal.GemFireVersion;
 import org.apache.geode.internal.process.ProcessUtils;
-import org.apache.geode.management.internal.cli.json.GfJsonArray;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 
@@ -805,8 +804,7 @@ public class AbstractLauncherServiceStateTest {
           GfJsonObject gfJsonObject = new GfJsonObject(json);
 
           Status status = valueOfDescription(gfJsonObject.getString(JSON_STATUS));
-          List<String> jvmArguments = Arrays
-              .asList(GfJsonArray.toStringArray(gfJsonObject.getJSONArray(JSON_JVMARGUMENTS)));
+          List<String> jvmArguments = gfJsonObject.getJSONArray(JSON_JVMARGUMENTS).toStringList();
 
           return new TestState(status, gfJsonObject.getString(JSON_STATUSMESSAGE),
               gfJsonObject.getLong(JSON_TIMESTAMP), gfJsonObject.getString(JSON_LOCATION),
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonArrayTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonArrayTest.java
index 0b62275..ce67c4b 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonArrayTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonArrayTest.java
@@ -17,11 +17,6 @@ package org.apache.geode.management.internal.cli.json;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.junit.Before;
 import org.junit.Test;
 
@@ -64,15 +59,15 @@ public class GfJsonArrayTest {
     gfJsonArray = new GfJsonArray(new String[] {"a", "b", "c"});
 
     assertThat(gfJsonArray.size()).isEqualTo(3);
-    assertThat(gfJsonArray.get(0)).isEqualTo("a");
-    assertThat(gfJsonArray.get(1)).isEqualTo("b");
-    assertThat(gfJsonArray.get(2)).isEqualTo("c");
+    assertThat(gfJsonArray.getString(0)).isEqualTo("a");
+    assertThat(gfJsonArray.getString(1)).isEqualTo("b");
+    assertThat(gfJsonArray.getString(2)).isEqualTo("c");
   }
 
   @Test
   public void addSingleObject() throws Exception {
     gfJsonArray.put("a");
-    assertThat(gfJsonArray.get(0)).isEqualTo("a");
+    assertThat(gfJsonArray.getString(0)).isEqualTo("a");
     assertThat(gfJsonArray.toString()).isEqualTo("[\"a\"]");
   }
 
@@ -82,50 +77,22 @@ public class GfJsonArrayTest {
     gfJsonArray.put("b");
     gfJsonArray.put("c");
 
-    assertThat(gfJsonArray.get(0)).isEqualTo("a");
-    assertThat(gfJsonArray.get(1)).isEqualTo("b");
-    assertThat(gfJsonArray.get(2)).isEqualTo("c");
+    assertThat(gfJsonArray.getString(0)).isEqualTo("a");
+    assertThat(gfJsonArray.getString(1)).isEqualTo("b");
+    assertThat(gfJsonArray.getString(2)).isEqualTo("c");
     assertThat(gfJsonArray.toString()).isEqualTo("[\"a\",\"b\",\"c\"]");
   }
 
   @Test
-  public void putCollection() throws Exception {
-    List<String> multiple = new ArrayList<>();
-    multiple.add("a");
-    multiple.add("b");
-    multiple.add("c");
-    gfJsonArray.put(multiple);
-    gfJsonArray.put(1, multiple);
-
-    assertThat(gfJsonArray.size()).isEqualTo(2);
-    assertThat(gfJsonArray.get(0).toString()).isEqualTo("[\"a\",\"b\",\"c\"]");
-    assertThat(gfJsonArray.get(1).toString()).isEqualTo("[\"a\",\"b\",\"c\"]");
-  }
-
-  @Test
-  public void putMap() throws Exception {
-    Map<Integer, String> multiple = new HashMap<>();
-    multiple.put(1, "a");
-    multiple.put(2, "b");
-    multiple.put(3, "c");
-    gfJsonArray.put(multiple);
-    gfJsonArray.put(1, multiple);
-
-    assertThat(gfJsonArray.size()).isEqualTo(2);
-    assertThat(gfJsonArray.get(0).toString()).isEqualTo("{1=a, 2=b, 3=c}");
-    assertThat(gfJsonArray.get(1).toString()).isEqualTo("{1=a, 2=b, 3=c}");
-  }
-
-  @Test
   public void putObject() throws Exception {
     GfJsonObject obj = new GfJsonObject(new Simple(1, "a"));
     gfJsonArray.put(obj);
     gfJsonArray.put(1, obj);
 
-    assertThat(gfJsonArray.getJSONObject(0).get("key")).isEqualTo(1);
-    assertThat(gfJsonArray.getJSONObject(0).get("value")).isEqualTo("a");
-    assertThat(gfJsonArray.getJSONObject(1).get("key")).isEqualTo(1);
-    assertThat(gfJsonArray.getJSONObject(1).get("value")).isEqualTo("a");
+    assertThat(gfJsonArray.getInternalJsonObject(0).getInt("key")).isEqualTo(1);
+    assertThat(gfJsonArray.getInternalJsonObject(0).getString("value")).isEqualTo("a");
+    assertThat(gfJsonArray.getInternalJsonObject(1).getInt("key")).isEqualTo(1);
+    assertThat(gfJsonArray.getInternalJsonObject(1).getString("value")).isEqualTo("a");
   }
 
   @Test
@@ -136,17 +103,5 @@ public class GfJsonArrayTest {
     assertThat(gfJsonArray.toString()).isEqualTo("[null,\"a\"]");
   }
 
-  @Test
-  public void stringifyArray() throws Exception {
-    List<String> multiple = new ArrayList<>();
-    multiple.add("a");
-    multiple.add("b");
-    gfJsonArray.put(multiple);
-    gfJsonArray.put(1, multiple);
-    gfJsonArray.put("c");
-
-    assertThat(GfJsonArray.toStringArray(gfJsonArray)).contains("[\"a\",\"b\"]", "[\"a\",\"b\"]",
-        "c");
-  }
 
 }
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonObjectTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonObjectTest.java
index 0f5082a..1a6e2a9 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonObjectTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/GfJsonObjectTest.java
@@ -44,6 +44,35 @@ public class GfJsonObjectTest {
     }
   }
 
+  public static class GetMethodReturnsObjectReferencingMe {
+    private String id;
+    private GetMethodReturnsObjectReferencingMe peer;
+
+    static GetMethodReturnsObjectReferencingMe createTestInstance() {
+      GetMethodReturnsObjectReferencingMe inst1 = new GetMethodReturnsObjectReferencingMe();
+      inst1.id = "instance1";
+      GetMethodReturnsObjectReferencingMe inst2 = new GetMethodReturnsObjectReferencingMe();
+      inst2.id = "instance2";
+      inst1.peer = inst2;
+      inst2.peer = inst1;
+      return inst1;
+    }
+
+    public String getId() {
+      return id;
+    }
+
+    public void setId(String id) {
+      this.id = id;
+    }
+
+    public GetMethodReturnsObjectReferencingMe getPeer() {
+      return peer;
+    }
+
+  }
+
+
   @Before
   public void setup() {
     gfJsonObject = new GfJsonObject();
@@ -63,6 +92,13 @@ public class GfJsonObjectTest {
   }
 
   @Test
+  public void addBidirectionalReferenceObject() throws GfJsonException {
+    // JSONObject.cyclicDepChkEnabled.set(true);
+    // JSONObject.cyclicDependencySet.set(new HashSet());
+    new GfJsonObject(new GetMethodReturnsObjectReferencingMe());
+  }
+
+  @Test
   public void addRawObject() throws Exception {
     gfJsonObject = new GfJsonObject("{\"key\":1}");
     assertThat(gfJsonObject.getString("key")).isEqualTo("1");
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/InfoResultDataTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/InfoResultDataTest.java
index eecc99c..1bec524 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/InfoResultDataTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/InfoResultDataTest.java
@@ -49,12 +49,12 @@ public class InfoResultDataTest {
     ResultData data = result.addAsFile("content.zip", "file contents", "a message", false);
 
     assertThat(result.getGfJsonObject().getJSONObject("content").getJSONArray("__bytes__")
-        .getJSONObject(0).getString("fileName")).isEqualTo("content.zip");
+        .getInternalJsonObject(0).getString("fileName")).isEqualTo("content.zip");
     assertThat(result.getGfJsonObject().getJSONObject("content").getJSONArray("__bytes__")
-        .getJSONObject(0).getString("fileType")).isEqualTo("1");
+        .getInternalJsonObject(0).getString("fileType")).isEqualTo("1");
     assertThat(result.getGfJsonObject().getJSONObject("content").getJSONArray("__bytes__")
-        .getJSONObject(0).getString("fileMessage")).isEqualTo("a message");
+        .getInternalJsonObject(0).getString("fileMessage")).isEqualTo("a message");
     assertThat(result.getGfJsonObject().getJSONObject("content").getJSONArray("__bytes__")
-        .getJSONObject(0).getString("fileData").length()).isGreaterThan(0);
+        .getInternalJsonObject(0).getString("fileData").length()).isGreaterThan(0);
   }
 }
diff --git a/geode-core/src/test/resources/expected-pom.xml b/geode-core/src/test/resources/expected-pom.xml
index 5b44b60..6790b99 100644
--- a/geode-core/src/test/resources/expected-pom.xml
+++ b/geode-core/src/test/resources/expected-pom.xml
@@ -280,11 +280,6 @@
     </dependency>
     <dependency>
       <groupId>org.apache.geode</groupId>
-      <artifactId>geode-json</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.geode</groupId>
       <artifactId>geode-management</artifactId>
       <scope>compile</scope>
     </dependency>
diff --git a/geode-dunit/build.gradle b/geode-dunit/build.gradle
index 5f94ecc..67906e3 100755
--- a/geode-dunit/build.gradle
+++ b/geode-dunit/build.gradle
@@ -25,7 +25,6 @@ dependencies {
   compile(project(':geode-junit')) {
     exclude module: 'geode-core'
   }
-  compile(project(':geode-json'))
 
   compile('com.jayway.jsonpath:json-path')
   compile('org.apache.logging.log4j:log4j-api')
diff --git a/geode-dunit/src/main/java/org/apache/geode/pdx/JSONFormatVerifyUtility.java b/geode-dunit/src/main/java/org/apache/geode/pdx/JSONFormatVerifyUtility.java
index cd15354..8b5af7c 100644
--- a/geode-dunit/src/main/java/org/apache/geode/pdx/JSONFormatVerifyUtility.java
+++ b/geode-dunit/src/main/java/org/apache/geode/pdx/JSONFormatVerifyUtility.java
@@ -15,12 +15,16 @@
 
 package org.apache.geode.pdx;
 
-import org.json.JSONObject;
+
 import org.junit.Assert;
 
+import org.apache.geode.management.internal.cli.json.GfJsonException;
+import org.apache.geode.management.internal.cli.json.GfJsonObject;
+
 public class JSONFormatVerifyUtility {
-  static void verifyJsonWithJavaObject(String json, TestObjectForJSONFormatter testObject) {
-    JSONObject jsonObject = new JSONObject(json);
+  static void verifyJsonWithJavaObject(String json, TestObjectForJSONFormatter testObject)
+      throws GfJsonException {
+    GfJsonObject jsonObject = new GfJsonObject(json);
 
     // Testcase-1: Validate json string against the pdxInstance.
     // validation for primitive types
@@ -39,31 +43,37 @@ public class JSONFormatVerifyUtility {
     Assert.assertEquals("VerifyPdxInstanceToJson: bigDec type values are not matched",
         testObject.getW_bigDec().longValue(), jsonObject.getLong(testObject.getW_bigDecFN()));
 
-    // vlidation for array types
+    // validation for array types
     Assert.assertEquals("VerifyPdxInstanceToJson: Byte[] type values are not matched",
         (int) testObject.getW_byteArray()[1],
-        jsonObject.getJSONArray(testObject.getW_byteArrayFN()).getInt(1));
+        jsonObject.getJSONArray(testObject.getW_byteArrayFN()).getInternalJsonArray().get(1)
+            .asInt());
     Assert.assertEquals("VerifyPdxInstanceToJson: Double[] type values are not matched",
         testObject.getW_doubleArray()[0],
-        jsonObject.getJSONArray(testObject.getW_doubleArrayFN()).getDouble(0), 0);
+        jsonObject.getJSONArray(testObject.getW_doubleArrayFN()).getInternalJsonArray().get(0)
+            .asDouble(0),
+        0);
     Assert.assertEquals("VerifyPdxInstanceToJson: String[] type values are not matched",
         testObject.getW_strArray()[2],
-        jsonObject.getJSONArray(testObject.getW_strArrayFN()).getString(2));
+        jsonObject.getJSONArray(testObject.getW_strArrayFN()).getInternalJsonArray().get(2)
+            .textValue());
 
     // validation for collection types
     Assert.assertEquals("VerifyPdxInstanceToJson: list type values are not matched",
         testObject.getC_list().get(0),
-        jsonObject.getJSONArray(testObject.getC_listFN()).getString(0));
+        jsonObject.getJSONArray(testObject.getC_listFN()).getInternalJsonArray().get(0)
+            .textValue());
 
     Assert.assertEquals("VerifyPdxInstanceToJson: stack type values are not matched",
         testObject.getC_stack().get(2),
-        jsonObject.getJSONArray(testObject.getC_stackFN()).getString(2));
+        jsonObject.getJSONArray(testObject.getC_stackFN()).getInternalJsonArray().get(2)
+            .textValue());
 
     // validation for Map
     Assert.assertEquals("VerifyPdxInstanceToJson: Map type values are not matched",
         testObject.getM_empByCity().get("Ahmedabad").get(0).getFname(),
         jsonObject.getJSONObject(testObject.getM_empByCityFN()).getJSONArray("Ahmedabad")
-            .getJSONObject(0).getString("fname"));
+            .getInternalJsonObject(0).getString("fname"));
 
     // validation Enum
     Assert.assertEquals("VerifyPdxInstanceToJson: Enum type values are not matched",
diff --git a/geode-dunit/src/test/resources/expected-pom.xml b/geode-dunit/src/test/resources/expected-pom.xml
index f7d2e1b..2d1edf3 100644
--- a/geode-dunit/src/test/resources/expected-pom.xml
+++ b/geode-dunit/src/test/resources/expected-pom.xml
@@ -63,11 +63,6 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.apache.geode</groupId>
-      <artifactId>geode-json</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
       <groupId>com.jayway.jsonpath</groupId>
       <artifactId>json-path</artifactId>
       <scope>compile</scope>
diff --git a/geode-junit/src/main/java/org/apache/geode/pdx/TestObjectForJSONFormatter.java b/geode-junit/src/main/java/org/apache/geode/pdx/TestObjectForJSONFormatter.java
index 364dff6..85fd4a8 100755
--- a/geode-junit/src/main/java/org/apache/geode/pdx/TestObjectForJSONFormatter.java
+++ b/geode-junit/src/main/java/org/apache/geode/pdx/TestObjectForJSONFormatter.java
@@ -29,8 +29,10 @@ import java.util.Queue;
 import java.util.Set;
 import java.util.Stack;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import org.apache.geode.management.internal.cli.json.GfJsonException;
+import org.apache.geode.management.internal.cli.json.GfJsonObject;
 
 enum Day {
   Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
@@ -97,9 +99,10 @@ public class TestObjectForJSONFormatter implements PdxSerializable {
 
   public TestObjectForJSONFormatter() {}
 
-  public String addClassTypeToJson(String json) throws JSONException {
-    JSONObject jsonObj = new JSONObject(json);
-    jsonObj.put("@type", "org.apache.geode.pdx.TestObjectForJSONFormatter");
+  public String addClassTypeToJson(String json) throws GfJsonException {
+    GfJsonObject jsonObj = new GfJsonObject(json);
+    ((ObjectNode) jsonObj.getInternalJsonObject()).put("@type",
+        "org.apache.geode.pdx.TestObjectForJSONFormatter");
     return jsonObj.toString();
   }
 
diff --git a/geode-web-api/build.gradle b/geode-web-api/build.gradle
index cdea6c8..418e0d7 100644
--- a/geode-web-api/build.gradle
+++ b/geode-web-api/build.gradle
@@ -24,6 +24,8 @@ dependencies {
   compile(platform(project(':boms:geode-all-bom')))
   compileOnly(platform(project(':boms:geode-all-bom')))
 
+  integrationTestCompile(project(':geode-json'))
+  
   compileOnly(project(':geode-core'))
 
   compileOnly('javax.servlet:javax.servlet-api')
diff --git a/geode-junit/src/main/java/org/apache/geode/test/matchers/JsonEquivalence.java b/geode-web-api/src/integrationTest/java/org/apache/geode/test/matchers/JsonEquivalence.java
similarity index 100%
rename from geode-junit/src/main/java/org/apache/geode/test/matchers/JsonEquivalence.java
rename to geode-web-api/src/integrationTest/java/org/apache/geode/test/matchers/JsonEquivalence.java