Merge "Add gson handler and tests"
diff --git a/gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java b/gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java
new file mode 100644
index 0000000..d48649e
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java
@@ -0,0 +1,50 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson;
+
+import com.google.gson.GsonBuilder;
+
+/**
+ * Provider used to serialize and deserialize policy objects via gson using jackson
+ * default behaviors and annotations.
+ */
+public class JacksonHandler extends GsonMessageBodyHandler {
+
+    /**
+     * Constructs the object.
+     */
+    public JacksonHandler() {
+        this(new GsonBuilder());
+    }
+
+    /**
+     * Constructs the object.
+     * @param builder builder to use to create the gson object
+     */
+    public JacksonHandler(GsonBuilder builder) {
+        super(builder
+                        .registerTypeAdapterFactory(new JacksonFieldAdapterFactory())
+                        .registerTypeAdapterFactory(new JacksonMethodAdapterFactory())
+                        .setExclusionStrategies(new JacksonExclusionStrategy())
+                        .create());
+    }
+
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/JacksonHandlerTest.java b/gson/src/test/java/org/onap/policy/common/gson/JacksonHandlerTest.java
new file mode 100644
index 0000000..5a49a40
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/JacksonHandlerTest.java
@@ -0,0 +1,132 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.ws.rs.core.MediaType;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonHandler;
+import org.onap.policy.common.gson.annotation.GsonJsonAnyGetter;
+import org.onap.policy.common.gson.annotation.GsonJsonAnySetter;
+
+public class JacksonHandlerTest {
+
+    @Test
+    public void test() throws Exception {
+        JacksonHandler hdlr = new JacksonHandler();
+
+        assertTrue(hdlr.isReadable(null, null, null, MediaType.APPLICATION_JSON_TYPE));
+        assertFalse(hdlr.isReadable(null, null, null, MediaType.TEXT_PLAIN_TYPE));
+
+        JsonObject expected = new JsonObject();
+        expected.addProperty("myId", 100);
+        expected.addProperty("value", "a value");
+        expected.addProperty("abc", "def");
+        expected.addProperty("hello", "world");
+
+        Data data = new Data();
+        data.id = 10;
+        data.value = "a value";
+        data.props = new HashMap<>();
+        data.props.put("abc", "def");
+        data.props.put("hello", "world");
+
+        /*
+         * Ensure everything serializes as expected.
+         */
+        ByteArrayOutputStream outstr = new ByteArrayOutputStream();
+        hdlr.writeTo(data, Data.class, Data.class, null, null, null, outstr);
+
+        StringReader rdr = new StringReader(outstr.toString("UTF-8"));
+        JsonObject json = new Gson().fromJson(rdr, JsonObject.class);
+
+        assertEquals(expected, json);
+
+        /*
+         * Ensure everything deserializes as expected.
+         */
+        Data data2 = (Data) hdlr.readFrom(Object.class, Data.class, null, null, null,
+                        new ByteArrayInputStream(outstr.toByteArray()));
+
+        // id is not serialized, so we must copy it manually before comparing
+        data2.id = data.id;
+
+        assertEquals(data.toString(), data2.toString());
+    }
+
+    /**
+     * This class includes all policy-specific gson annotations.
+     */
+    public static class Data {
+        protected int id;
+
+        protected String value;
+
+        protected Map<String, String> props;
+
+        public int getMyId() {
+            return 100;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        @GsonJsonAnyGetter
+        public Map<String, String> getProps() {
+            return props;
+        }
+
+        /**
+         * Sets a property.
+         * @param name property name
+         * @param value new value
+         */
+        @GsonJsonAnySetter
+        public void setProperty(String name, String value) {
+            if (props == null) {
+                props = new TreeMap<>();
+            }
+
+            props.put(name, value);
+        }
+
+        @Override
+        public String toString() {
+            return "Data [id=" + id + ", value=" + value + ", props=" + props + "]";
+        }
+    }
+}
diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml
index 2c8b0d7..c7bc8c4 100644
--- a/policy-endpoints/pom.xml
+++ b/policy-endpoints/pom.xml
@@ -195,6 +195,13 @@
         </dependency>
 
         <dependency>
+            <groupId>org.onap.policy.common</groupId>
+            <artifactId>utils-test</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
@@ -209,7 +216,6 @@
         <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
-            <version>3.11.1</version>
             <scope>test</scope>
         </dependency>
 
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java
index 9912761..ebed381 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java
@@ -31,6 +31,7 @@
 import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSource;
 import org.onap.policy.common.endpoints.event.comm.bus.UebTopicSink;
 import org.onap.policy.common.endpoints.event.comm.bus.UebTopicSource;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -229,35 +230,42 @@
     }
 
     @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public List<UebTopicSource> getUebTopicSources() {
         return UebTopicSource.factory.inventory();
     }
 
     @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public List<DmaapTopicSource> getDmaapTopicSources() {
         return DmaapTopicSource.factory.inventory();
     }
 
+    @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public List<NoopTopicSource> getNoopTopicSources() {
         return NoopTopicSource.factory.inventory();
     }
 
     @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public List<UebTopicSink> getUebTopicSinks() {
         return UebTopicSink.factory.inventory();
     }
 
     @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public List<DmaapTopicSink> getDmaapTopicSinks() {
         return DmaapTopicSink.factory.inventory();
     }
 
     @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public List<NoopTopicSink> getNoopTopicSinks() {
         return NoopTopicSink.factory.inventory();
@@ -325,6 +333,7 @@
      * @return list of managed endpoints
      */
     @JsonIgnore
+    @GsonJsonIgnore
     protected List<Startable> getEndpoints() {
         final List<Startable> endpoints = new ArrayList<>();
 
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java
index 9b2e6f5..1c2d6ee 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
  * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,6 +41,7 @@
 import org.onap.dmaap.mr.test.clients.ProtocolTypeConstants;
 import org.onap.policy.common.endpoints.event.comm.bus.DmaapTopicSinkFactory;
 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,6 +73,7 @@
          * The actual Cambria publisher.
          */
         @JsonIgnore
+        @GsonJsonIgnore
         protected volatile CambriaBatchingPublisher publisher;
 
         /**
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
index 2287486..01f9fbe 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
@@ -41,6 +41,7 @@
 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
 import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -270,6 +271,7 @@
     }
 
     @JsonIgnore
+    @GsonJsonIgnore
     @Override
     public String getPassword() {
         return password;
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
index 0c52aca..76ad116 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.onap.aaf.cadi.filter.CadiFilter;
 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -486,6 +487,7 @@
      * @return the password
      */
     @JsonIgnore
+    @GsonJsonIgnore
     public String getPassword() {
         return password;
     }
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java
index 19dde43..a311c0b 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java
@@ -33,6 +33,7 @@
 import org.onap.policy.common.endpoints.event.comm.bus.DmaapTopicPropertyBuilder;
 import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicPropertyBuilder;
 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class TopicEndpointProxyTest {
 
@@ -112,6 +113,16 @@
     }
 
     @Test
+    public void testSerialize() {
+        TopicEndpoint manager = new TopicEndpointProxy();
+
+        manager.addTopicSources(configuration);
+        manager.addTopicSinks(configuration);
+
+        new GsonTestUtils().compareGson(manager, TopicEndpointProxyTest.class);
+    }
+
+    @Test
     public void addTopicSources() {
         TopicEndpoint manager = new TopicEndpointProxy();
 
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java
index 56d3b47..83a94bd 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class BusTopicBaseTest extends TopicTestBase {
 
@@ -49,6 +50,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(base, BusTopicBaseTest.class);
+    }
+
+    @Test
     public void testGetApiKey() {
         assertEquals(MY_API_KEY, base.getApiKey());
     }
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java
index 7330e6f..cb6eb10 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.TopicListener;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class InlineBusTopicSinkTest extends TopicTestBase {
 
@@ -58,6 +59,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(sink, InlineBusTopicSinkTest.class);
+    }
+
+    @Test
     public void testInlineBusTopicSinkImpl() {
         // verify that different wrappers can be built
         sink = new InlineBusTopicSinkImpl(makeBuilder().build());
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java
index bf06410..aaab402 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class InlineDmaapTopicSinkTest extends TopicTestBase {
     private InlineDmaapTopicSink sink;
@@ -48,6 +49,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(sink, InlineDmaapTopicSinkTest.class);
+    }
+
+    @Test
     public void testToString() {
         assertTrue(sink.toString().startsWith("InlineDmaapTopicSink ["));
     }
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java
index 610070e..2516406 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class InlineUebTopicSinkTest extends TopicTestBase {
     private InlineUebTopicSink sink;
@@ -48,6 +49,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(sink, InlineUebTopicSinkTest.class);
+    }
+
+    @Test
     public void testToString() {
         assertTrue(sink.toString().startsWith("InlineUebTopicSink ["));
     }
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java
index d0e8569..f930fb6 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
 import org.onap.policy.common.endpoints.event.comm.TopicListener;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusConsumer.FilterableBusConsumer;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class SingleThreadedBusTopicSourceTest extends TopicTestBase {
     private Thread thread;
@@ -69,6 +70,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(source, SingleThreadedBusTopicSourceTest.class);
+    }
+
+    @Test
     public void testRegister() {
         source.register(listener);
         assertEquals(1, source.initCount);
@@ -146,7 +152,7 @@
                 // do nothing
             }
         };
-        
+
         assertNotNull(source2.makePollerThread());
     }
 
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java
index c744403..29c3459 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class SingleThreadedDmaapTopicSourceTest extends TopicTestBase {
     private SingleThreadedDmaapTopicSource source;
@@ -49,6 +50,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(source, SingleThreadedDmaapTopicSourceTest.class);
+    }
+
+    @Test
     public void testToString() {
         assertTrue(source.toString().startsWith("SingleThreadedDmaapTopicSource ["));
         source.shutdown();
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java
index b8cb0c1..99dc6fb 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-endpoints
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class SingleThreadedUebTopicSourceTest extends TopicTestBase {
     private SingleThreadedUebTopicSource source;
@@ -48,6 +49,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(source, SingleThreadedUebTopicSourceTest.class);
+    }
+
+    @Test
     public void testToString() {
         assertTrue(source.toString().startsWith("SingleThreadedUebTopicSource ["));
         source.shutdown();
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java
index 76883b3..a8ea84f 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java
@@ -2,14 +2,14 @@
  * ============LICENSE_START=======================================================
  * ONAP Policy Engine - Common Modules
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed 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.
@@ -37,6 +37,7 @@
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.TopicListener;
 import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 
 public class TopicBaseTest extends TopicTestBase {
 
@@ -48,7 +49,7 @@
     @Before
     public void setUp() {
         super.setUp();
-        
+
         base = new TopicBaseImpl(servers, MY_TOPIC);
     }
 
@@ -73,6 +74,11 @@
     }
 
     @Test
+    public void testSerialize() {
+        new GsonTestUtils().compareGson(base, TopicBaseTest.class);
+    }
+
+    @Test
     public void testRegister() {
         TopicListener listener = mock(TopicListener.class);
         base.register(listener);
@@ -246,7 +252,7 @@
 
         /**
          * Constructor.
-         * 
+         *
          * @param servers list of servers
          * @param topic topic name
          */
@@ -285,7 +291,7 @@
 
         /**
          * Adds an event to the list of recent events.
-         * 
+         *
          * @param event event to be added
          */
         public void addEvent(String event) {
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
index 3d80793..972fc66 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
@@ -39,6 +39,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.utils.gson.GsonTestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -233,6 +234,16 @@
     }
 
     @Test
+    public void testSerialize() {
+        HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", port, "/", false, true);
+        server.addServletPackage("/*", this.getClass().getPackage().getName());
+        server.addFilterClass("/*", TestFilter.class.getCanonicalName());
+
+        // ensure we can serialize the server
+        new GsonTestUtils().compareGson(server, HttpServerTest.class);
+    }
+
+    @Test
     public void testSingleServer() throws Exception {
         logger.info("-- testSingleServer() --");
 
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java
index 5778eee..c211881 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java
@@ -22,6 +22,7 @@
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.gson.annotations.SerializedName;
+import org.onap.policy.common.gson.annotation.GsonJsonProperty;
 
 /**
  * "ECHO" request and response supporting serialization and de-serialization via
@@ -29,10 +30,12 @@
  */
 public class RestEchoReqResp {
     @JsonProperty("reqId")
+    @GsonJsonProperty("reqId")
     @SerializedName("reqId")
     private int requestId;
 
     @JsonProperty("textValue")
+    @GsonJsonProperty("textValue")
     @SerializedName("textValue")
     private String text;
 
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.json
new file mode 100644
index 0000000..11624af
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.json
@@ -0,0 +1,74 @@
+{
+  "locked" : false,
+  "alive" : false,
+  "topicSources" : [ {
+    "servers" : [ "my-server" ],
+    "topic" : "ueb-source",
+    "recentEvents" : [ ],
+    "alive" : false,
+    "locked" : false,
+    "apiKey" : null,
+    "apiSecret" : null,
+    "useHttps" : true,
+    "allowSelfSignedCerts" : true,
+    "consumerGroup" : "${obj.topicSources[0].consumerGroup}",
+    "consumerInstance" : "${obj.topicSources[0].consumerInstance}",
+    "fetchTimeout" : 15000,
+    "fetchLimit" : 100,
+    "topicCommInfrastructure" : "UEB"
+  }, {
+    "servers" : [ "my-server" ],
+    "topic" : "dmaap-source",
+    "recentEvents" : [ ],
+    "alive" : false,
+    "locked" : false,
+    "apiKey" : "my-api-key",
+    "apiSecret" : "my-api-secret",
+    "useHttps" : true,
+    "allowSelfSignedCerts" : true,
+    "consumerGroup" : "my-cons-group",
+    "consumerInstance" : "my-cons-inst",
+    "fetchTimeout" : 101,
+    "fetchLimit" : 100,
+    "topicCommInfrastructure" : "DMAAP"
+  }, {
+    "servers" : [ "my-server" ],
+    "topic" : "noop-source",
+    "recentEvents" : [ ],
+    "alive" : false,
+    "locked" : false,
+    "topicCommInfrastructure" : "NOOP"
+  } ],
+  "topicSinks" : [ {
+    "servers" : [ "my-server" ],
+    "topic" : "ueb-sink",
+    "recentEvents" : [ ],
+    "alive" : false,
+    "locked" : false,
+    "apiKey" : null,
+    "apiSecret" : null,
+    "useHttps" : true,
+    "allowSelfSignedCerts" : true,
+    "topicCommInfrastructure" : "UEB",
+    "partitionKey" : "${obj.topicSinks[0].partitionKey}"
+  }, {
+    "servers" : [ "my-server" ],
+    "topic" : "dmaap-sink",
+    "recentEvents" : [ ],
+    "alive" : false,
+    "locked" : false,
+    "apiKey" : "my-api-key",
+    "apiSecret" : "my-api-secret",
+    "useHttps" : true,
+    "allowSelfSignedCerts" : true,
+    "topicCommInfrastructure" : "DMAAP",
+    "partitionKey" : "my-partition"
+  }, {
+    "servers" : [ "my-server" ],
+    "topic" : "noop-sink",
+    "recentEvents" : [ ],
+    "alive" : false,
+    "locked" : false,
+    "topicCommInfrastructure" : "NOOP"
+  } ]
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.json
new file mode 100644
index 0000000..49eafaf
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.json
@@ -0,0 +1,12 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "topicCommInfrastructure" : "NOOP"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.json
new file mode 100644
index 0000000..9831875
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.json
@@ -0,0 +1,13 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "topicCommInfrastructure" : "NOOP",
+  "partitionKey" : "my-partition"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.json
new file mode 100644
index 0000000..a83f5c9
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.json
@@ -0,0 +1,13 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "topicCommInfrastructure" : "DMAAP",
+  "partitionKey" : "my-partition"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.json
new file mode 100644
index 0000000..4ec0c80
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.json
@@ -0,0 +1,13 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "topicCommInfrastructure" : "UEB",
+  "partitionKey" : "my-partition"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.json
new file mode 100644
index 0000000..4f88025
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.json
@@ -0,0 +1,16 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "consumerGroup" : "my-cons-group",
+  "consumerInstance" : "my-cons-inst",
+  "fetchTimeout" : 101,
+  "fetchLimit" : 100,
+  "topicCommInfrastructure" : "NOOP"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.json
new file mode 100644
index 0000000..82e4b3f
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.json
@@ -0,0 +1,16 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "consumerGroup" : "my-cons-group",
+  "consumerInstance" : "my-cons-inst",
+  "fetchTimeout" : 101,
+  "fetchLimit" : 100,
+  "topicCommInfrastructure" : "DMAAP"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.json
new file mode 100644
index 0000000..4eeacc6
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.json
@@ -0,0 +1,16 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "apiKey" : "my-api-key",
+  "apiSecret" : "my-api-secret",
+  "useHttps" : true,
+  "allowSelfSignedCerts" : true,
+  "consumerGroup" : "my-cons-group",
+  "consumerInstance" : "my-cons-inst",
+  "fetchTimeout" : 101,
+  "fetchLimit" : 100,
+  "topicCommInfrastructure" : "UEB"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.json
new file mode 100644
index 0000000..7431854
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.json
@@ -0,0 +1,8 @@
+{
+  "servers" : [ "svra", "svrb" ],
+  "topic" : "my-topic",
+  "recentEvents" : [ ],
+  "alive" : false,
+  "locked" : false,
+  "topicCommInfrastructure" : "NOOP"
+}
diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/http/server/internal/HttpServerTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/http/server/internal/HttpServerTest.json
new file mode 100644
index 0000000..5f4a7a9
--- /dev/null
+++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/http/server/internal/HttpServerTest.json
@@ -0,0 +1,7 @@
+{
+    "aaf": false,
+    "alive": false,
+    "host": "localhost",
+    "name": "echo",
+    "port": ${obj.port}
+}
diff --git a/utils-test/pom.xml b/utils-test/pom.xml
index bf36472..fffe610 100644
--- a/utils-test/pom.xml
+++ b/utils-test/pom.xml
@@ -44,7 +44,6 @@
         <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
-            <version>3.11.1</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -57,6 +56,11 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.onap.policy.common</groupId>
+            <artifactId>gson</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-api-mockito</artifactId>
             <scope>test</scope>
diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonSerializer.java b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonSerializer.java
new file mode 100644
index 0000000..db9c1c7
--- /dev/null
+++ b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonSerializer.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-management
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.gson;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import java.io.IOException;
+
+/**
+ * Gson serializer, providing stub implementation of "read".
+ *
+ * @param <T> type of object that this serializes
+ */
+public abstract class GsonSerializer<T> extends TypeAdapter<T> {
+    @Override
+    public T read(JsonReader in) throws IOException {
+        throw new UnsupportedOperationException("read from pseudo TypeAdapter");
+    }
+}
diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtils.java b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtils.java
new file mode 100644
index 0000000..bfdca97
--- /dev/null
+++ b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtils.java
@@ -0,0 +1,314 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-management
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.gson;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utilities used to test encoding and decoding of Policy objects.
+ */
+public class GsonTestUtils {
+
+    private static final Logger logger = LoggerFactory.getLogger(GsonTestUtils.class);
+
+    /**
+     * Matches script items, of the form ${xxx}, within text.
+     */
+    private static final Pattern SCRIPT_PAT = Pattern.compile("\\$\\{([^}]+)\\}");
+
+    /**
+     * Engine used to interpolate strings before they're compared.
+     */
+    private static volatile ScriptEngine engine = null;
+
+    /**
+     * Used to encode and decode an object via gson.
+     */
+    private Gson gson;
+
+    /**
+     * Constructs the object.
+     */
+    public GsonTestUtils() {
+        GsonTestUtils other = new GsonTestUtilsBuilder().build();
+
+        gson = other.gson;
+    }
+
+    /**
+     * Constructs the object.
+     *
+     * @param gson used to encode via gson
+     */
+    protected GsonTestUtils(Gson gson) {
+        this.gson = gson;
+    }
+
+    public Gson getGson() {
+        return gson;
+    }
+
+    /**
+     * Serializes and then deserializes an object using gson.
+     *
+     * @param object the object to be serialized
+     * @param clazz the class of object to deserialize
+     * @return the deserialized object
+     */
+    public <T> T gsonRoundTrip(T object, Class<T> clazz) {
+        String sgson = gsonEncode(object);
+        return gson.fromJson(sgson, clazz);
+    }
+
+    /**
+     * Encodes an object using gson and then compares it to the expected value, after
+     * sorting the elements. The class name is used to find the json file, whose contents
+     * is interpolated (i.e., script elements, of the form ${obj.xxx}, are expanded).
+     *
+     * @param object the object to be encoded
+     * @param expected the expected value
+     * @throws Exception if the file cannot be read
+     */
+    public void compareGson(Object object, Class<?> expected) {
+        compareGson(object, new File(expected.getSimpleName() + ".json"));
+    }
+
+    /**
+     * Encodes an object using gson and then compares it to the expected value, after
+     * sorting the elements. The content of the file is interpolated (i.e., script
+     * elements, of the form ${obj.xxx}, are expanded).
+     *
+     * @param object the object to be encoded
+     * @param expected the expected value
+     * @throws Exception if the file cannot be read
+     */
+    public void compareGson(Object object, File expected) {
+        // file is not required to have a full path - find it via getResource()
+        URL url = object.getClass().getResource(expected.getName());
+        if (url == null) {
+            throw new JsonParseException(new FileNotFoundException(expected.getName()));
+        }
+
+        String expectedText;
+        try {
+            expectedText = readFile(new File(url.getFile()));
+
+        } catch (IOException e) {
+            throw new JsonParseException("error reading: " + expected, e);
+        }
+
+        compareGson(object, expectedText);
+    }
+
+    /**
+     * Encodes an object using gson and then compares it to the expected value, after
+     * sorting the elements. The expected value is interpolated (i.e., script elements, of
+     * the form ${obj.xxx}, are expanded).
+     *
+     * @param object the object to be encoded
+     * @param expected the expected value
+     */
+    public void compareGson(Object object, String expected) {
+        String result = applyScripts(expected, object);
+        compareGson(object, gson.fromJson(result, JsonElement.class));
+    }
+
+    /**
+     * Encodes an object using gson and then compares it to the expected value, after
+     * sorting the elements.
+     *
+     * @param object the object to be encoded
+     * @param expected the expected value
+     */
+    public void compareGson(Object object, JsonElement expected) {
+        String sgson = gsonEncode(object);
+
+        JsonElement gsonjo = reorder(gson.fromJson(sgson, JsonElement.class));
+        JsonElement expjo = reorder(expected);
+
+        assertEquals(expjo.toString(), gsonjo.toString());
+    }
+
+    /**
+     * Reads the content of a file.
+     * @param file file to read
+     * @return the content of the file
+     * @throws IOException if an error occurs
+     */
+    protected String readFile(File file) throws IOException {
+        return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
+    }
+
+
+    /**
+     * Interpolates script elements, of the form ${obj.xxx}, within some text. The script
+     * is evaluated via javascript, where "obj" references the object used by each script
+     * element.
+     *
+     * @param object object to be used by the script
+     * @param text text to be evaluated
+     * @return the text, after interpolating the script elements
+     */
+    public String applyScripts(String text, Object object) {
+        Matcher mat = SCRIPT_PAT.matcher(text);
+        if (!mat.find()) {
+            // contains no script elements - just return it as is
+            return text;
+        }
+
+        // create the engine and bind the object to the variable, "obj"
+        if (engine == null) {
+            // race condition here, but it's ok to overwrite with a new engine
+            engine = new ScriptEngineManager().getEngineByName("javascript");
+        }
+
+        Bindings bindings = engine.createBindings();
+        bindings.put("obj", object);
+
+        // work our way through the text, interpolating script elements as we go
+        StringBuilder bldr = new StringBuilder();
+        int ilast = 0;
+        mat.reset();
+        while (mat.find(ilast)) {
+            // append segment that appears between last match and this
+            int inext = mat.start();
+            bldr.append(text.substring(ilast, inext));
+
+            // next match begins after the current match
+            ilast = mat.end();
+
+            // interpolate the script
+            String script = mat.group(1);
+            try {
+                Object result = engine.eval(script, bindings);
+                bldr.append(result == null ? "null" : result.toString());
+
+            } catch (ScriptException e) {
+                throw new RuntimeException("cannot expand element: " + mat.group(), e);
+            }
+        }
+
+        // append final segment
+        bldr.append(text.substring(ilast));
+
+        return bldr.toString();
+    }
+
+    /**
+     * Encodes an object using gson.
+     *
+     * @param object the object to be encoded
+     * @return the encoded object
+     */
+    public String gsonEncode(Object object) {
+        String sgson = gson.toJson(object);
+        logger.debug("gson=" + sgson);
+        return sgson;
+    }
+
+    /**
+     * Recursively re-orders a json object, arranging the keys alphabetically and removing
+     * null items.
+     *
+     * @param jsonObj object from which nulls are to be removed
+     * @return a new object, without the null items
+     */
+    public JsonObject reorder(JsonObject jsonObj) {
+        JsonObject newjo = new JsonObject();
+
+        // sort the keys before copying to the new object
+        List<Entry<String, JsonElement>> sortedSet = new ArrayList<>(jsonObj.entrySet());
+        Collections.sort(sortedSet, (left, right) -> left.getKey().compareTo(right.getKey()));
+
+        for (Entry<String, JsonElement> ent : sortedSet) {
+            JsonElement val = ent.getValue();
+            if (val.isJsonNull()) {
+                continue;
+            }
+
+            newjo.add(ent.getKey(), reorder(val));
+        }
+
+        return newjo;
+    }
+
+    /**
+     * Recursively re-orders a json array, arranging the keys alphabetically and removing
+     * null items.
+     *
+     * @param jsonArray array from which nulls are to be removed
+     * @return a new array, with null items removed from all elements
+     */
+    public JsonArray reorder(JsonArray jsonArray) {
+        JsonArray newarr = new JsonArray();
+        for (JsonElement ent : jsonArray) {
+            newarr.add(reorder(ent));
+        }
+
+        return newarr;
+    }
+
+    /**
+     * Recursively re-orders a json element, arranging the keys alphabetically and
+     * removing null items.
+     *
+     * @param jsonEl element from which nulls are to be removed
+     * @return a new element, with null items removed
+     */
+    public JsonElement reorder(JsonElement jsonEl) {
+        if (jsonEl == null) {
+            return null;
+
+        } else if (jsonEl.isJsonObject()) {
+            return reorder(jsonEl.getAsJsonObject());
+
+        } else if (jsonEl.isJsonArray()) {
+            return reorder(jsonEl.getAsJsonArray());
+
+        } else {
+            return jsonEl;
+        }
+    }
+}
diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java
new file mode 100644
index 0000000..1f697fd
--- /dev/null
+++ b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-management
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.gson;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+import org.onap.policy.common.gson.JacksonHandler;
+
+/**
+ * Used to builder a utility class.
+ */
+public class GsonTestUtilsBuilder {
+    private final GsonBuilder gsonBldr;
+
+    /**
+     * Constructs the object.
+     */
+    public GsonTestUtilsBuilder() {
+        gsonBldr = new GsonBuilder();
+
+        // register jackson behaviors with the builder
+        new JacksonHandler(gsonBldr);
+    }
+
+    /**
+     * Builds the utility.
+     *
+     * @return a new utility
+     */
+    public GsonTestUtils build() {
+        return new GsonTestUtils(gsonBldr.create());
+    }
+
+    /**
+     * Adds gson support for serializing a mock of a class.
+     *
+     * @param clazz mocked class to be supported
+     * @param sgson gson serializer
+     */
+    protected <T> void addMock(Class<T> clazz, TypeAdapterFactory sgson) {
+        gsonBldr.registerTypeAdapterFactory(sgson);
+    }
+}
diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonSerializerTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonSerializerTest.java
new file mode 100644
index 0000000..82f5ede
--- /dev/null
+++ b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonSerializerTest.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.gson;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import org.junit.Test;
+
+public class GsonSerializerTest {
+
+    @Test
+    public void testReadJsonReader() {
+        JsonReader rdr = new JsonReader(new StringReader("10"));
+
+        GsonSerializer<Object> ser = new GsonSerializer<Object>() {
+            @Override
+            public void write(JsonWriter out, Object value) throws IOException {
+                // do nothing
+            }
+        };
+
+        assertThatThrownBy(() -> ser.read(rdr)).isInstanceOf(UnsupportedOperationException.class)
+                        .hasMessage("read from pseudo TypeAdapter");
+    }
+}
diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilderTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilderTest.java
new file mode 100644
index 0000000..3e4244d
--- /dev/null
+++ b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilderTest.java
@@ -0,0 +1,93 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.gson;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.gson.Gson;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GsonTestUtilsBuilderTest {
+
+    private GsonTestUtilsBuilder bldr;
+    private GsonTestUtils utils;
+
+    @Before
+    public void setUp() {
+        bldr = new MyBuilder();
+        utils = bldr.build();
+    }
+
+    @Test
+    public void testBuilderAddMock() {
+        PreMock pre = mock(PreMock.class);
+        when(pre.getId()).thenReturn(2000);
+
+        assertEquals("{\"name\":2000}", utils.gsonEncode(pre));
+    }
+
+    /**
+     * Builder that provides an adapter for mock(PreMock.class).
+     */
+    private static class MyBuilder extends GsonTestUtilsBuilder {
+        public MyBuilder() {
+            TypeAdapterFactory sgson = new TypeAdapterFactory() {
+                @Override
+                public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
+                    Class<? super T> clazz = type.getRawType();
+
+                    if (PreMock.class.isAssignableFrom(clazz)) {
+                        return new GsonSerializer<T>() {
+                            @Override
+                            public void write(JsonWriter out, T value) throws IOException {
+                                PreMock obj = (PreMock) value;
+                                out.beginObject().name("name").value(obj.getId()).endObject();
+                            }
+                        };
+                    }
+
+                    return null;
+                }
+            };
+
+            addMock(PreMock.class, sgson);
+        }
+    }
+
+    /**
+     * Class that will be mocked.
+     */
+    public static class PreMock {
+        protected int id = 1000;
+
+        public int getId() {
+            return id;
+        }
+    }
+}
diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsTest.java
new file mode 100644
index 0000000..39cde7d
--- /dev/null
+++ b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsTest.java
@@ -0,0 +1,248 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.gson;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import javax.script.ScriptException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GsonTestUtilsTest {
+    private static final String HELLO = "hello";
+
+    private GsonTestUtils utils;
+
+    @Before
+    public void setUp() {
+        utils = new GsonTestUtils();
+    }
+
+    @Test
+    public void testGetGson() {
+        assertNotNull(utils.getGson());
+    }
+
+    @Test
+    public void testGsonRoundTrip() {
+        Data data = new Data();
+        data.setId(500);
+
+        // try with null text
+        data.setText(null);
+        assertEquals(data.toString(), utils.gsonRoundTrip(data, Data.class).toString());
+
+        // try with non-null text
+        data.setText(HELLO);
+        assertEquals(data.toString(), utils.gsonRoundTrip(data, Data.class).toString());
+    }
+
+    @Test
+    public void testCompareGsonObjectClass_testCompareGsonObjectFile() {
+        Data data = new Data();
+        data.setId(500);
+        data.setText(HELLO);
+
+        utils.compareGson(data, GsonTestUtilsTest.class);
+
+        // file not found
+        assertThatThrownBy(() -> utils.compareGson(data,
+                        new File(GsonTestUtilsTest.class.getSimpleName() + "-NotFound.json")))
+                                        .isInstanceOf(JsonParseException.class)
+                                        .hasCauseInstanceOf(FileNotFoundException.class);
+
+        // force I/O error while reading file
+        GsonTestUtils utils2 = new GsonTestUtils() {
+            @Override
+            protected String readFile(File file) throws IOException {
+                throw new IOException("expected exception");
+            }
+        };
+        assertThatThrownBy(() -> utils2.compareGson(data, GsonTestUtilsTest.class))
+                        .isInstanceOf(JsonParseException.class).hasCauseInstanceOf(IOException.class)
+                        .hasMessage("error reading: GsonTestUtilsTest.json");
+    }
+
+    @Test
+    public void testCompareGsonObjectString() {
+        Data data = new Data();
+        data.setId(600);
+        data.setText(HELLO);
+
+        utils.compareGson(data, "{'id': ${obj.id}, 'text': '${obj.text}'}".replace('\'', '"'));
+    }
+
+    @Test
+    public void testCompareGsonObjectJsonElement() {
+        Data data = new Data();
+        data.setId(650);
+        data.setText(HELLO);
+
+        JsonObject json = new JsonObject();
+        json.addProperty("id", data.getId());
+        json.addProperty("text", data.getText());
+
+        utils.compareGson(data, json);
+
+        // mismatch
+        data.setText("world");
+        assertThatThrownBy(() -> utils.compareGson(data, json)).isInstanceOf(AssertionError.class);
+    }
+
+    @Test
+    public void testApplyScripts() {
+        Data data = new Data();
+        data.setId(700);
+        data.setText(HELLO);
+
+        String result = utils.applyScripts("no interpolation", data);
+        assertEquals("no interpolation", result);
+
+        result = utils.applyScripts("${obj.id} at start, ${obj.text} in middle, and end ${obj.id}", data);
+        assertEquals("700 at start, hello in middle, and end 700", result);
+
+        // try null value
+        data.setText(null);
+        result = utils.applyScripts("use ${obj.text} this", data);
+        assertEquals("use null this", result);
+
+        assertThatThrownBy(() -> utils.applyScripts("use ${obj.text} this", null)).isInstanceOf(RuntimeException.class)
+                        .hasCauseInstanceOf(ScriptException.class).hasMessage("cannot expand element: ${obj.text}");
+    }
+
+    @Test
+    public void testReorderJsonObject() {
+        // insert properties in a non-alphabetical order
+        JsonObject inner = new JsonObject();
+        inner.addProperty("objBint", 100);
+        inner.add("objBNull", JsonNull.INSTANCE);
+        inner.addProperty("objB", true);
+
+        JsonArray arr = new JsonArray();
+        arr.add(110);
+        arr.add(inner);
+        arr.add(false);
+
+        JsonObject outer = new JsonObject();
+        outer.add("objANull", JsonNull.INSTANCE);
+        outer.addProperty("objA", true);
+        outer.addProperty("objAStr", "obj-a-string");
+        outer.add("nested-array", arr);
+
+        outer = utils.reorder(outer);
+        assertEquals("{'nested-array':[110,{'objB':true,'objBint':100},false],'objA':true,'objAStr':'obj-a-string'}"
+                        .replace('\'', '"'), outer.toString());
+    }
+
+    @Test
+    public void testReorderJsonArray() {
+        // insert properties in a non-alphabetical order
+        JsonObject inner = new JsonObject();
+        inner.add("objCNull", JsonNull.INSTANCE);
+        inner.addProperty("objCStr", "obj-c-string");
+        inner.addProperty("objC", true);
+
+        JsonArray arr = new JsonArray();
+        arr.add(200);
+        arr.add(inner);
+        arr.add(false);
+
+        arr = utils.reorder(arr);
+        assertEquals("[200,{'objC':true,'objCStr':'obj-c-string'},false]".replace('\'', '"'), arr.toString());
+    }
+
+    @Test
+    public void testReorderJsonElement() {
+        // null element
+        JsonElement jsonEl = null;
+        assertNull(utils.reorder(jsonEl));
+
+        // object element
+        JsonObject obj = new JsonObject();
+        obj.add("objDNull", JsonNull.INSTANCE);
+        obj.addProperty("objDStr", "obj-d-string");
+        obj.addProperty("objD", true);
+        jsonEl = obj;
+        jsonEl = utils.reorder(jsonEl);
+        assertEquals("{'objD':true,'objDStr':'obj-d-string'}".replace('\'', '"'), jsonEl.toString());
+
+        // boolean
+        jsonEl = obj.get("objD");
+        jsonEl = utils.reorder(jsonEl);
+        assertEquals("true", jsonEl.toString());
+
+        // JsonNull
+        jsonEl = JsonNull.INSTANCE;
+        jsonEl = utils.reorder(jsonEl);
+        assertEquals("null", jsonEl.toString());
+
+        // array element
+        JsonObject inner = new JsonObject();
+        inner.add("objENull", JsonNull.INSTANCE);
+        inner.addProperty("objEStr", "obj-e-string");
+        inner.addProperty("objE", true);
+
+        JsonArray arr = new JsonArray();
+        arr.add(300);
+        arr.add(inner);
+        arr.add(false);
+        jsonEl = arr;
+        jsonEl = utils.reorder(jsonEl);
+        assertEquals("[300,{'objE':true,'objEStr':'obj-e-string'},false]".replace('\'', '"'), jsonEl.toString());
+    }
+
+    public static class Data {
+        private int id;
+        private String text;
+
+        public int getId() {
+            return id;
+        }
+
+        public void setId(int id) {
+            this.id = id;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public void setText(String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String toString() {
+            return "Data [id=" + id + ", text=" + text + "]";
+        }
+    }
+}
diff --git a/utils-test/src/test/resources/org/onap/policy/common/utils/gson/GsonTestUtilsTest.json b/utils-test/src/test/resources/org/onap/policy/common/utils/gson/GsonTestUtilsTest.json
new file mode 100644
index 0000000..ff7ed70
--- /dev/null
+++ b/utils-test/src/test/resources/org/onap/policy/common/utils/gson/GsonTestUtilsTest.json
@@ -0,0 +1,4 @@
+{
+    "id": ${obj.id},
+    "text": "${obj.text}"
+}