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

bschuchardt pushed a commit to branch feature/GEODE-6196
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/feature/GEODE-6196 by this 
push:
     new efa4757  removed TypedJson, replacing with QueryResultFormatter
efa4757 is described below

commit efa4757126a7e642fd87f4c7ab6a227fa9f81d28
Author: Bruce Schuchardt <[email protected]>
AuthorDate: Tue Mar 5 15:13:34 2019 -0800

    removed TypedJson, replacing with QueryResultFormatter
    
    most of TypedJson's internals were replaced so I just renamed it to
    QueryResultFormatter to better show its intended purpose.
    
    Object traversal depth is now limited to the element-count being passed
    by the QueryDataFunction function.  This will prevent the stack-overflow
    problems seen in GEODE-1842.
---
 .../geode/tools/pulse/PulseDataExportTest.java     |   2 +-
 ... QueryResultFormatterQueryIntegrationTest.java} |  40 +-
 .../management/DataQueryEngineIntegrationTest.java |  14 +-
 ...=> QueryResultFormatterPdxIntegrationTest.java} |  18 +-
 .../internal/beans/QueryDataFunction.java          |   4 +-
 .../internal/cli/json/QueryResultFormatter.java    | 447 +++++++++++++++++++++
 .../management/internal/cli/json/TypedJson.java    | 359 -----------------
 ...JsonTest.java => QueryResultFormatterTest.java} |  56 +--
 8 files changed, 517 insertions(+), 423 deletions(-)

diff --git 
a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseDataExportTest.java
 
b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseDataExportTest.java
index 5fb6cfa..9b1b81c 100644
--- 
a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseDataExportTest.java
+++ 
b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseDataExportTest.java
@@ -57,6 +57,6 @@ public class PulseDataExportTest {
             .hasStatusCode(200)
             .hasResponseBody()
             .isEqualToIgnoringWhitespace(
-                
"{\"result\":[[\"java.lang.String\",\"value1\"],[\"java.lang.String\",\"value2\"],[\"java.lang.String\",\"value3\"]]}");
+                
"{\"result\":[[\"[Lorg.apache.geode.management.model.SubOrder;\",[[\"org.apache.geode.management.model.SubOrder\",{\"id\":\"null1\",\"items\":[\"java.util.ArrayList\",[]]}],null]]]}");
   }
 }
diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/TypedJsonQueryIntegrationTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryResultFormatterQueryIntegrationTest.java
similarity index 65%
rename from 
geode-core/src/integrationTest/java/org/apache/geode/cache/query/TypedJsonQueryIntegrationTest.java
rename to 
geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryResultFormatterQueryIntegrationTest.java
index 82ffada..1e9373c 100644
--- 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/TypedJsonQueryIntegrationTest.java
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryResultFormatterQueryIntegrationTest.java
@@ -24,21 +24,21 @@ import org.apache.geode.cache.query.data.Position;
 import org.apache.geode.cache.util.ObjectSizer;
 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.json.TypedJson;
-import 
org.apache.geode.management.internal.cli.json.TypedJsonPdxIntegrationTest;
+import org.apache.geode.management.internal.cli.json.QueryResultFormatter;
+import 
org.apache.geode.management.internal.cli.json.QueryResultFormatterPdxIntegrationTest;
 import org.apache.geode.test.junit.categories.OQLQueryTest;
 
 /**
- * Integration tests for {@link TypedJson} querying {@link Portfolio}.
+ * Integration tests for {@link QueryResultFormatter} querying {@link 
Portfolio}.
  * <p>
  *
- * Extracted from {@link TypedJsonPdxIntegrationTest}.
+ * Extracted from {@link QueryResultFormatterPdxIntegrationTest}.
  * <p>
  *
  * TODO: add real assertions
  */
 @Category({OQLQueryTest.class})
-public class TypedJsonQueryIntegrationTest {
+public class QueryResultFormatterQueryIntegrationTest {
 
   private static final String RESULT = "result";
 
@@ -46,18 +46,19 @@ public class TypedJsonQueryIntegrationTest {
   public void testUserObject() throws Exception {
     Portfolio p = new Portfolio(2);
 
-    TypedJson typedJson = new TypedJson(RESULT, p, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, p);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
   public void testUserObjectArray() throws Exception {
     Portfolio[] portfolios = createPortfoliosAndPositions(2);
 
-    TypedJson typedJson = new TypedJson(RESULT, portfolios, 100);
+    QueryResultFormatter queryResultFormatter =
+        new QueryResultFormatter(100).add(RESULT, portfolios);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
@@ -65,24 +66,25 @@ public class TypedJsonQueryIntegrationTest {
     Portfolio[] portfolios = createPortfoliosAndPositions(1000);
     System.out.println("Size Of port " + 
ObjectSizer.REFLECTION_SIZE.sizeof(portfolios));
 
-    TypedJson typedJson = new TypedJson(RESULT, portfolios, 100);
-    System.out.println("Size Of json " + 
ObjectSizer.REFLECTION_SIZE.sizeof(typedJson));
+    QueryResultFormatter queryResultFormatter =
+        new QueryResultFormatter(100).add(RESULT, portfolios);
+    System.out.println("Size Of json " + 
ObjectSizer.REFLECTION_SIZE.sizeof(queryResultFormatter));
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
   public void testQueryLike() throws Exception {
     Portfolio[] portfolios = createPortfoliosAndPositions(2);
 
-    TypedJson typedJson = new TypedJson(RESULT, null, 100);
-    typedJson.add("member", "server1");
-    // checkResult(typedJson); -- fails
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, null);
+    queryResultFormatter.add("member", "server1");
+    // checkResult(queryResultFormatter); -- fails
 
     for (int i = 0; i < 2; i++) {
-      typedJson.add(RESULT, portfolios[i]);
+      queryResultFormatter.add(RESULT, portfolios[i]);
     }
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   private Portfolio[] createPortfoliosAndPositions(final int count) {
@@ -94,8 +96,8 @@ public class TypedJsonQueryIntegrationTest {
     return portfolios;
   }
 
-  private void checkResult(final TypedJson typedJson) throws GfJsonException {
-    GfJsonObject gfJsonObject = new GfJsonObject(typedJson.toString());
+  private void checkResult(final QueryResultFormatter queryResultFormatter) 
throws GfJsonException {
+    GfJsonObject gfJsonObject = new 
GfJsonObject(queryResultFormatter.toString());
     System.out.println(gfJsonObject);
     assertThat(gfJsonObject.get(RESULT)).isNotNull();
   }
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 daf69fa..43be476 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
@@ -98,7 +98,7 @@ public class DataQueryEngineIntegrationTest {
     region.put("order1", order);
 
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.management.model.Order\",{\"items\":[\"java.util.Collection\",{\"0\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":[\"java.lang.String\",\"Book\"],\"itemId\":[\"java.lang.String\",\"ID_1\"],\"order\":[\"org.apache.geode.management.model.Order\",\"org.apache.geode.management.model.Order\"]}],\"1\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":[\"java.lang.String\",\"Book\"],\"itemId\":[\"java.lang.String\",\"I
 [...]
+        
"{\"result\":[[\"org.apache.geode.management.model.Order\",{\"id\":\"test\",\"items\":[\"java.util.ArrayList\",{\"0\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":\"Book\",\"itemId\":\"ID_1\",\"order\":\"duplicate
 
org.apache.geode.management.model.Order\"}],\"1\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":\"Book\",\"itemId\":\"ID_2\",\"order\":\"duplicate
 
org.apache.geode.management.model.Order\"}],\"2\":[\"org.apache.geode.management.mod
 [...]
     Object result = queryEngine.queryForJsonResult(QUERY_1, 0, 
queryResultSetLimit,
         queryCollectionsDepth);
     String queryResult = (String) result;
@@ -131,7 +131,7 @@ public class DataQueryEngineIntegrationTest {
         queryCollectionsDepth);
 
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.management.model.Order\",{\"items\":[\"java.util.Collection\",{\"0\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":[\"java.lang.String\",\"Book\"],\"itemId\":[\"java.lang.String\",\"ID_1\"],\"order\":[\"org.apache.geode.management.model.Order\",{\"items\":[\"java.util.Collection\",{}],\"id\":[\"java.lang.String\",\"ORDER_ID_1\"]}]}],\"1\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":[\"java.lang.String\",\"B
 [...]
+        
"{\"result\":[[\"org.apache.geode.management.model.Order\",{\"id\":\"test\",\"items\":[\"java.util.ArrayList\",{\"0\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":\"Book\",\"itemId\":\"ID_1\",\"order\":[\"org.apache.geode.management.model.Order\",{\"id\":\"ORDER_ID_1\",\"items\":[\"java.util.ArrayList\",{}]}]}],\"1\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":\"Book\",\"itemId\":\"ID_2\",\"order\":[\"org.apache.geode.management.model.Orde
 [...]
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
@@ -161,7 +161,7 @@ public class DataQueryEngineIntegrationTest {
     String queryResult = queryEngine.queryForJsonResult(QUERY_1, 0, 
queryResultSetLimit,
         queryCollectionsDepth);
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.management.model.Order\",{\"items\":[\"java.util.Collection\",{\"0\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":[\"java.lang.String\",\"Book\"],\"itemId\":[\"java.lang.String\",\"ID_1\"],\"order\":[\"org.apache.geode.management.model.Order\",{\"items\":[\"java.util.Collection\",\"java.util.ArrayList\"],\"id\":[\"java.lang.String\",\"ORDER_ID_1\"]}]}],\"1\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":[\"j
 [...]
+        
"{\"result\":[[\"org.apache.geode.management.model.Order\",{\"id\":\"ORDER_TEST\",\"items\":[\"java.util.ArrayList\",{\"0\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":\"Book\",\"itemId\":\"ID_1\",\"order\":[\"org.apache.geode.management.model.Order\",{\"id\":\"ORDER_ID_1\",\"items\":[\"java.util.ArrayList\",{\"0\":\"duplicate
 
org.apache.geode.management.model.Item\",\"1\":[\"org.apache.geode.management.model.Item\",{\"itemDescription\":\"Book\",\"itemId\":\"
 [...]
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
@@ -277,7 +277,7 @@ public class DataQueryEngineIntegrationTest {
     String queryResult = queryEngine.queryForJsonResult(QUERY_1, 0, 
queryResultSetLimit,
         queryCollectionsDepth);
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.management.model.SubOrder\",{\"items\":[\"java.util.Collection\",{}],\"id\":[\"java.lang.String\",\"null1\"]}]]}";
+        
"{\"result\":[[\"org.apache.geode.management.model.SubOrder\",{\"id\":\"null1\",\"items\":[\"java.util.ArrayList\",{}]}]]}";
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
@@ -300,7 +300,7 @@ public class DataQueryEngineIntegrationTest {
     String queryResult = queryEngine.queryForJsonResult(QUERY_1, 0, 
queryResultSetLimit,
         queryCollectionsDepth);
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.pdx.PdxInstance\",{\"ID\":[\"java.lang.Integer\",111],\"status\":[\"java.lang.String\",\"active\"],\"secId\":[\"java.lang.String\",\"IBM\"]}]]}";
+        
"{\"result\":[[\"org.apache.geode.pdx.internal.PdxInstanceImpl\",{\"ID\":111,\"status\":\"active\",\"secId\":\"IBM\"}]]}";
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
@@ -318,7 +318,7 @@ public class DataQueryEngineIntegrationTest {
     String queryResult = queryEngine.queryForJsonResult(QUERY_1, 0, 
queryResultSetLimit,
         queryCollectionsDepth);
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.management.model.SubOrder[]\",[{\"items\":[\"java.util.Collection\",{}],\"id\":[\"java.lang.String\",\"null1\"]},null]]]}";
+        
"{\"result\":[[\"[Lorg.apache.geode.management.model.SubOrder;\",[[\"org.apache.geode.management.model.SubOrder\",{\"id\":\"null1\",\"items\":[\"java.util.ArrayList\",{}]}],null]]]}";
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
@@ -336,7 +336,7 @@ public class DataQueryEngineIntegrationTest {
     String queryResult = queryEngine.queryForJsonResult(QUERY_1, 0, 
queryResultSetLimit,
         queryCollectionsDepth);
     String expectedResult =
-        
"{\"result\":[[\"org.apache.geode.management.model.SubOrder[]\",[{\"items\":[\"java.util.Collection\",{}],\"id\":[\"java.lang.String\",\"null1\"]},null]]]}";
+        
"{\"result\":[[\"[Lorg.apache.geode.management.model.SubOrder;\",[[\"org.apache.geode.management.model.SubOrder\",{\"id\":\"null1\",\"items\":[\"java.util.ArrayList\",{}]}],null]]]}";
     assertThat(queryResult).isEqualToIgnoringWhitespace(expectedResult);
 
     // If not correct JSON format this will throw a JSONException
diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/cli/json/TypedJsonPdxIntegrationTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/management/internal/cli/json/QueryResultFormatterPdxIntegrationTest.java
similarity index 85%
rename from 
geode-core/src/integrationTest/java/org/apache/geode/management/internal/cli/json/TypedJsonPdxIntegrationTest.java
rename to 
geode-core/src/integrationTest/java/org/apache/geode/management/internal/cli/json/QueryResultFormatterPdxIntegrationTest.java
index ab93adc..dfe9f8c 100644
--- 
a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/cli/json/TypedJsonPdxIntegrationTest.java
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/management/internal/cli/json/QueryResultFormatterPdxIntegrationTest.java
@@ -34,12 +34,12 @@ import org.apache.geode.pdx.PdxInstanceFactory;
 import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl;
 
 /**
- * Integration tests for {@link TypedJson}.
+ * Integration tests for {@link QueryResultFormatter}.
  * <p>
  *
  * TODO: add actual assertions
  */
-public class TypedJsonPdxIntegrationTest {
+public class QueryResultFormatterPdxIntegrationTest {
 
   private static final String RESULT = "result";
 
@@ -71,9 +71,10 @@ public class TypedJsonPdxIntegrationTest {
     pdxInstanceFactory.writeObject("object", new SerializableObject(2));
     PdxInstance pdxInstance = pdxInstanceFactory.create();
 
-    TypedJson typedJson = new TypedJson(RESULT, pdxInstance, 100);
+    QueryResultFormatter queryResultFormatter =
+        new QueryResultFormatter(100).add(RESULT, pdxInstance);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
@@ -83,13 +84,14 @@ public class TypedJsonPdxIntegrationTest {
     pdxInstanceFactory.writeString("secId", "IBM");
     PdxContainer pdxContainer = new PdxContainer(pdxInstanceFactory.create(), 
1);
 
-    TypedJson typedJson = new TypedJson(RESULT, pdxContainer, 100);
+    QueryResultFormatter queryResultFormatter =
+        new QueryResultFormatter(100).add(RESULT, pdxContainer);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
-  private void checkResult(TypedJson typedJson) throws GfJsonException {
-    GfJsonObject gfJsonObject = new GfJsonObject(typedJson.toString());
+  private void checkResult(QueryResultFormatter queryResultFormatter) throws 
GfJsonException {
+    GfJsonObject gfJsonObject = new 
GfJsonObject(queryResultFormatter.toString());
     System.out.println(gfJsonObject);
     assertThat(gfJsonObject.get(RESULT)).isNotNull();
   }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/beans/QueryDataFunction.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/beans/QueryDataFunction.java
index 809e724..9b1fb91 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/beans/QueryDataFunction.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/beans/QueryDataFunction.java
@@ -43,7 +43,7 @@ import 
org.apache.geode.internal.cache.PartitionedRegionHelper;
 import org.apache.geode.internal.cache.execute.InternalFunction;
 import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.management.internal.ManagementConstants;
-import org.apache.geode.management.internal.cli.json.TypedJson;
+import org.apache.geode.management.internal.cli.json.QueryResultFormatter;
 
 /**
  * This function is executed on one or multiple members based on the member 
input to
@@ -118,7 +118,7 @@ public class QueryDataFunction implements Function, 
InternalEntity {
     queryString = applyLimitClause(queryString, limit, queryResultSetLimit);
 
     try {
-      TypedJson result = new TypedJson(queryCollectionsDepth);
+      QueryResultFormatter result = new 
QueryResultFormatter(queryCollectionsDepth);
 
       Region region = cache.getRegion(regionName);
 
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
new file mode 100644
index 0000000..935f1d7
--- /dev/null
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/QueryResultFormatter.java
@@ -0,0 +1,447 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+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;
+import com.fasterxml.jackson.core.JsonStreamContext;
+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 com.fasterxml.jackson.databind.ser.PropertyWriter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+
+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;
+  private final SimpleModule mapperModule;
+
+  /**
+   * map contains the named objects to be serialized
+   */
+  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.
+   *
+   * @param maxCollectionElements limit on collection elements and depth-first 
object traversal
+   */
+  public QueryResultFormatter(int maxCollectionElements) {
+    this(maxCollectionElements, maxCollectionElements);
+  }
+
+  /**
+   * 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?
+   */
+  public QueryResultFormatter(int maxCollectionElements, int 
serializationDepth) {
+    this.map = new LinkedHashMap<>();
+
+    this.serializedObjects = new IdentityHashMap<>();
+    this.mapper = new ObjectMapper();
+    this.mapperModule = new SimpleModule() {
+      @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);
+          }
+        });
+      }
+    };
+    // 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.setFilterProvider(new 
SimpleFilterProvider().setDefaultFilter(new DepthFilter(4)));
+    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);
+
+  }
+
+  /**
+   * After instantiating a formatter add the objects you want to be formatted
+   * using this method. Typically this will be add("result", queryResult)
+   */
+  public 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);
+    }
+    return this;
+  }
+
+  /* non-javadoc use Jackson to serialize added objects into JSON format */
+  @Override
+  public String toString() {
+    StringWriter w = new StringWriter();
+    synchronized (w.getBuffer()) {
+      try {
+        return this.write(w).toString();
+      } catch (Exception e) {
+        e.printStackTrace();
+        return null;
+      }
+    }
+  }
+
+
+  private Writer write(Writer writer) throws GfJsonException {
+    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('}');
+
+      return writer;
+    } catch (IOException exception) {
+      throw new GfJsonException(exception);
+    }
+  }
+
+  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;
+  }
+
+
+  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);
+      }
+    }
+  }
+
+
+  /* found on StackOverflow */
+  static class DepthFilter extends SimpleBeanPropertyFilter {
+    private final int maxDepth;
+
+    public DepthFilter(int maxDepth) {
+      super();
+      this.maxDepth = maxDepth;
+    }
+
+    private int calcDepth(JsonGenerator jgen) {
+      JsonStreamContext streamContext = jgen.getOutputContext();
+      int depth = -1;
+      while (streamContext != null) {
+        streamContext = streamContext.getParent();
+        depth++;
+      }
+      return depth;
+    }
+
+    @Override
+    public void serializeAsField(Object pojo, JsonGenerator gen, 
SerializerProvider provider,
+        PropertyWriter writer)
+        throws Exception {
+      int depth = calcDepth(gen);
+      System.out.println("depth of " + pojo.getClass().getSimpleName() + " is 
" + depth);
+      if (depth <= maxDepth) {
+        writer.serializeAsField(pojo, gen, provider);
+      }
+      // comment this if you don't want {} placeholders
+      else {
+        writer.serializeAsOmittedField(pojo, gen, provider);
+      }
+    }
+
+  }
+
+  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();
+    }
+
+    public 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();
+    }
+
+    public 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();
+    }
+
+    public 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;
+    }
+  }
+}
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/TypedJson.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/TypedJson.java
deleted file mode 100644
index 4e22e69..0000000
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/TypedJson.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
- * agreements. See the NOTICE file distributed with this work for additional 
information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the 
License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software 
distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
- * or implied. See the License for the specific language governing permissions 
and limitations under
- * the License.
- */
-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.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.JsonSerializer;
-import com.fasterxml.jackson.databind.ObjectMapper;
-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 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 TypedJson {
-
-  ObjectMapper mapper;
-  SimpleModule mapperModule;
-
-  Map<Object, List<Object>> forbidden = new java.util.IdentityHashMap<Object, 
List<Object>>();
-
-  boolean addCommaBeforeNextElement;
-
-  private Map<String, List<Object>> map;
-
-  private int maxCollectionElements;
-
-
-  {
-    mapper = new ObjectMapper();
-    mapperModule = new SimpleModule();
-    // todo: Collection.class is probably too generic. Is there another way to
-    // limit the number of elements generated by Jackson w/o using a 
serializer for Collection?
-    mapperModule.addSerializer(Collection.class, new 
TypedJsonCollectionSerializer());
-    mapperModule.addSerializer(PdxInstance.class, new 
TypedJsonPdxInstanceSerializer());
-    mapperModule.addSerializer(StructImpl.class, new 
TypedJsonStructSerializer());
-    mapperModule.addSerializer(Region.Entry.class, new 
TypedJsonRegionEntrySerializer());
-    mapper.registerModule(mapperModule);
-    mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
-    // todo: we need type information for enums but Jackson doesn't seem to do 
that
-    // -- look at the standard EnumSerializer to see if it can be configured
-    mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
-    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
-  }
-
-
-  public TypedJson(int maxCollectionElements) {
-    this.map = new LinkedHashMap<>();
-    this.maxCollectionElements = maxCollectionElements;
-  }
-
-  /**
-   * Constructor for tests. This is equivalent to
-   * new TypedJson(maxCollectionElements).add(key, value)
-   */
-  public TypedJson(String key, Object value, int maxCollectionElements) {
-    List<Object> list = new ArrayList<>(1);
-    this.map = new LinkedHashMap<>();
-    if (value != null) {
-      list.add(value);
-    }
-    this.map.put(key, list);
-    this.maxCollectionElements = maxCollectionElements;
-  }
-
-  /**
-   * User can build on this object by adding Objects against a key.
-   *
-   * TypedJson result = new TypedJson(); result.add(KEY,object); If users add 
more objects against
-   * the same key the newly added object will be appended to the existing key 
forming an array of
-   * objects.
-   *
-   * If the KEY is a new one then it will be a key map value.
-   *
-   * @param key Key against which an object will be added
-   * @param value Object to be added
-   * @return TypedJson object
-   */
-  public TypedJson add(String key, Object value) {
-    List<Object> list = this.map.get(key);
-    if (list != null) {
-      list.add(value);
-    } else {
-      list = new ArrayList<>();
-      list.add(value);
-      this.map.put(key, list);
-    }
-    return this;
-  }
-
-  @Override
-  public String toString() {
-    StringWriter w = new StringWriter();
-    synchronized (w.getBuffer()) {
-      try {
-        return this.write(w).toString();
-      } catch (Exception e) {
-        e.printStackTrace();
-        return null;
-      }
-    }
-  }
-
-
-  private Writer write(Writer writer) throws GfJsonException {
-    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());
-        addCommaBeforeNextElement = false;
-        addComma = true;
-      }
-      writer.write('}');
-
-      return writer;
-    } catch (IOException exception) {
-      throw new GfJsonException(exception);
-    }
-  }
-
-  private Writer writeList(Writer writer, List<Object> values) throws 
GfJsonException {
-    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(',');
-          }
-          // System.out.format("BRUCE: writeList is serializing %s\n", 
values.get(i));
-          mapper.writerFor(values.get(i).getClass()).writeValue(writer, 
values.get(i));
-
-          addCommaBeforeNextElement = false;
-          addComma = true;
-        }
-      }
-      writer.write(']');
-    } catch (IOException e) {
-      throw new GfJsonException(e);
-    }
-    return writer;
-  }
-
-
-
-  class TypedJsonCollectionSerializer extends JsonSerializer<Collection> {
-    @Override
-    public void serializeWithType(Collection value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      gen.setCurrentValue(value);
-      boolean isArray = value.getClass().isArray();
-      WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
-          typeSer.typeId(value, JsonToken.START_ARRAY));
-      _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();
-    }
-
-    public void _serialize(Collection value, JsonGenerator gen) throws 
IOException {
-      // System.out.println("BRUCE: collection serializer starting for 
collection " + value);
-      Iterator<Object> objects = value.iterator();
-      for (int i = 0; i < maxCollectionElements && objects.hasNext(); i++) {
-        Object nextObject = objects.next();
-        // System.out.format("BRUCE: collection serializer writing #%s: %s\n", 
i, nextObject);
-        gen.writeObject(nextObject);
-        // System.out.println("BRUCE: collection serializer done writing #" + 
i);
-      }
-    }
-
-    @Override
-    public Class<Collection> handledType() {
-      return Collection.class;
-    }
-  }
-
-  class TypedJsonMapSerializer extends JsonSerializer<Map> {
-
-    @Override
-    public void serializeWithType(Map value, JsonGenerator gen,
-        SerializerProvider serializers, TypeSerializer typeSer)
-        throws IOException {
-      gen.setCurrentValue(value);
-      WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
-          typeSer.typeId(value, JsonToken.START_OBJECT));
-      // typeSer.writeTypePrefix(gen, typeSer.typeId(value, 
JsonToken.START_ARRAY));
-      _serialize(value, gen);
-      // typeSer.writeTypeSuffix(gen, typeSer.typeId(value, 
JsonToken.START_ARRAY));
-      typeSer.writeTypeSuffix(gen, typeIdDef);
-    }
-
-    @Override
-    public void serialize(Map value, JsonGenerator gen, SerializerProvider 
serializers)
-        throws IOException {
-      gen.writeStartObject();
-      _serialize(value, gen);
-      gen.writeEndObject();
-    }
-
-    public void _serialize(Map value, JsonGenerator gen) throws IOException {
-      Iterator<Map.Entry> entries = value.entrySet().iterator();
-      for (int i = 0; i < maxCollectionElements && entries.hasNext(); i++) {
-        Map.Entry entry = entries.next();
-        // System.out.format("BRUCE: map serializer writing key %s value %s 
value class %s\n",
-        // entry.getKey(), entry.getValue(), 
entry.getValue().getClass().getName());
-        // gen.writeObjectField(entry.getKey().toString(), entry.getValue());
-        // try {
-        gen.writeFieldName(entry.getKey().toString());
-        gen.writeObject(entry.getValue());
-        // } catch (JsonGenerationException e) {
-        // System.out.println("BRUCE: exception serializing value for " +
-        // entry.getKey().toString());
-        // throw e;
-        // }
-        // System.out.println("BRUCE: map serializer done writing key " + 
entry.getKey());
-      }
-    }
-
-    @Override
-    public Class<Map> handledType() {
-      return Map.class;
-    }
-  }
-
-  static class TypedJsonPdxInstanceSerializer 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();
-    }
-
-    public 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;
-    }
-  }
-
-  static class TypedJsonStructSerializer 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();
-    }
-
-    public 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;
-    }
-  }
-
-  static class TypedJsonRegionEntrySerializer 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;
-    }
-  }
-}
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/TypedJsonTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/QueryResultFormatterTest.java
similarity index 64%
rename from 
geode-core/src/test/java/org/apache/geode/management/internal/cli/json/TypedJsonTest.java
rename to 
geode-core/src/test/java/org/apache/geode/management/internal/cli/json/QueryResultFormatterTest.java
index 9a6996d..b076d22 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/TypedJsonTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/json/QueryResultFormatterTest.java
@@ -34,18 +34,18 @@ import org.junit.Test;
  *
  * TODO: add actual assertions
  */
-public class TypedJsonTest {
+public class QueryResultFormatterTest {
 
   private static final String RESULT = "result";
 
   @Test
   public void canBeMocked() throws Exception {
-    TypedJson mockTypedJson = mock(TypedJson.class);
+    QueryResultFormatter mockQueryResultFormatter = 
mock(QueryResultFormatter.class);
     Object value = new Object();
 
-    mockTypedJson.add("key", value);
+    mockQueryResultFormatter.add("key", value);
 
-    verify(mockTypedJson, times(1)).add("key", value);
+    verify(mockQueryResultFormatter, times(1)).add("key", value);
   }
 
   @Test
@@ -55,9 +55,9 @@ public class TypedJsonTest {
     list.add("TWO");
     list.add("THREE");
 
-    TypedJson typedJson = new TypedJson(RESULT, list, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, list);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
@@ -67,9 +67,9 @@ public class TypedJsonTest {
       intArray[i] = i;
     }
 
-    TypedJson typedJson = new TypedJson(RESULT, intArray, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, intArray);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
@@ -79,25 +79,27 @@ public class TypedJsonTest {
       list.add("BIG_COLL_" + i);
     }
 
-    TypedJson typedJson = new TypedJson(RESULT, list, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, list);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
   public void testEnumContainer() throws Exception {
     EnumContainer enumContainer = new EnumContainer(Currency.DIME);
 
-    TypedJson typedJson = new TypedJson(RESULT, enumContainer, 100);
+    QueryResultFormatter queryResultFormatter =
+        new QueryResultFormatter(100).add(RESULT, enumContainer);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
   public void testEnum() throws Exception {
-    TypedJson typedJson = new TypedJson(RESULT, Currency.DIME, 100);
+    QueryResultFormatter queryResultFormatter =
+        new QueryResultFormatter(100).add(RESULT, Currency.DIME);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
@@ -108,9 +110,9 @@ public class TypedJsonTest {
     list.add(Currency.QUARTER);
     list.add(Currency.NICKLE);
 
-    TypedJson typedJson = new TypedJson(RESULT, list, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, list);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
@@ -121,32 +123,32 @@ public class TypedJsonTest {
     map.put("3", "THREE");
     map.put("4", "FOUR");
 
-    TypedJson typedJson = new TypedJson(RESULT, map, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, map);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
   public void testBigDecimal() throws Exception {
     BigDecimal dc = new BigDecimal(20);
 
-    TypedJson typedJson = new TypedJson(RESULT, dc, 100);
+    QueryResultFormatter queryResultFormatter = new 
QueryResultFormatter(100).add(RESULT, dc);
 
-    checkResult(typedJson);
+    checkResult(queryResultFormatter);
   }
 
   @Test
   public void testObjects() throws Exception {
     Object object = new Object();
 
-    TypedJson typedJson = new TypedJson(100);
-    typedJson.add(RESULT, object);
-    checkResult(typedJson);
+    QueryResultFormatter queryResultFormatter = new QueryResultFormatter(100);
+    queryResultFormatter.add(RESULT, object);
+    checkResult(queryResultFormatter);
   }
 
-  private void checkResult(final TypedJson typedJson) throws GfJsonException {
-    String jsonString = typedJson.toString();
-    System.out.println("typedJson.toString=" + jsonString);
+  private void checkResult(final QueryResultFormatter queryResultFormatter) 
throws GfJsonException {
+    String jsonString = queryResultFormatter.toString();
+    System.out.println("queryResultFormatter.toString=" + jsonString);
     GfJsonObject gfJsonObject = new GfJsonObject(jsonString);
     System.out.println("gfJsonObject=" + gfJsonObject);
     assertThat(gfJsonObject.get(RESULT)).isNotNull();
@@ -154,7 +156,7 @@ public class TypedJsonTest {
 
   private enum Currency {
     PENNY, NICKLE, DIME, QUARTER
-  };
+  }
 
   private static class EnumContainer {
 

Reply via email to