changeset 244:42f6d962eb8f

Add helper test class to make json string handling/creation/testing better Reviewed-by: jerboaa, jkang, stooke Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-July/024327.html Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024451.html Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-September/024807.html
author Christopher Koehler <chkoehle@redhat.com>
date Fri, 01 Sep 2017 13:08:57 -0400
parents 0a6be16cb261
children 1bcd159ffaf7
files tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/tests/util/ContentWrapperTest.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/tests/util/ResponseSetWrapperTest.java tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/ContentWrapper.java tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/HttpTestUtil.java tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/ResponseSetWrapper.java
diffstat 6 files changed, 1730 insertions(+), 372 deletions(-) [+]
line wrap: on
line diff
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java	Mon Sep 04 09:09:12 2017 +0200
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java	Fri Sep 01 13:08:57 2017 -0400
@@ -36,11 +36,16 @@
 
 package com.redhat.thermostat.gateway.service.jvms;
 
+import com.redhat.thermostat.gateway.tests.utils.ContentWrapper.Array;
+import com.redhat.thermostat.gateway.tests.utils.ContentWrapper.Map;
 import static org.junit.Assert.assertEquals;
 
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
+import com.redhat.thermostat.gateway.tests.utils.ContentWrapper;
+import com.redhat.thermostat.gateway.tests.utils.HttpTestUtil;
+import com.redhat.thermostat.gateway.tests.utils.ResponseSetWrapper;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.util.StringContentProvider;
 import org.eclipse.jetty.http.HttpMethod;
@@ -52,42 +57,109 @@
 
     private static final String jvmsUrl = baseUrl + "/jvms/0.0.1";
 
-    private final String postData = "[{ \"agentId\" : \"aid\", \"jvmId\" : \"jid1\", \"jvmPid\" : 1, \"startTime\" :" +
-            "{ \"$numberLong\" : \"1495727607481\" }, \"stopTime\" : { \"$numberLong\" : \"-9223372036854775808\" }," +
-            " \"javaVersion\" : \"1.8.0_131\", \"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-            " \"mainClass\" : \"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", \"vmArguments\" :" +
-            " \"-Djline.log.jul=true\", \"jvmInfo\" : \"mixed mode\", \"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" :" +
-            " \"25.131-b12\", \"environment\" : [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"" +
-            " }, { \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, { \"key\" : \"GDMSESSION\"," +
-            " \"value\" : \"i3\" }, { \"key\" : \"fish_greeting\", \"value\" : \"\" }, { \"key\" : \"TERM\", \"value\" :" +
-            " \"xterm-256color\" }, { \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"LANG\", \"value\" :" +
-            " \"en_US.UTF-8\" }, { \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }," +
-            " { \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }," +
-            " { \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }," +
-            " { \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
-            "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }]," +
-            " \"uid\" : 1000, \"username\" : \"user\"},{ \"agentId\" : \"aid\", \"jvmId\" : \"jid2\", \"jvmPid\" : 2," +
-            " \"startTime\" : { \"$numberLong\" : \"1495727607481\" }, \"stopTime\" : { \"$numberLong\" : \"1495727607482\" }," +
-            " \"javaVersion\" : \"1.8.0_131\", \"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-            " \"mainClass\" : \"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", \"vmArguments\" :" +
-            " \"-Djline.log.jul=true\", \"jvmInfo\" : \"mixed mode\", \"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" : \"25.131-b12\"," +
-            " \"environment\" : [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }," +
-            " { \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, { \"key\" : \"GDMSESSION\"," +
-            " \"value\" : \"i3\" }, { \"key\" : \"fish_greeting\", \"value\" : \"\" }, { \"key\" : \"TERM\", \"value\" :" +
-            " \"xterm-256color\" }, { \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"LANG\", \"value\" :" +
-            " \"en_US.UTF-8\" }, { \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }," +
-            " { \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }," +
-            " { \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }," +
-            " { \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }," +
-            " { \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }]," +
-            " \"uid\" : 1000, \"username\" : \"user\"}]";
+    private static final ContentWrapper postDataWrapper = new ContentWrapper().addToResponse(
+         Map.of("agentId", "aid",
+                "startTime", Map.of("$numberLong", "1495727607481"),
+                "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                "uid", 1000,
+                "jvmName", "vm",
+                "stopTime", Map.of("$numberLong", "-9223372036854775808"),
+                "username", "user",
+                "jvmInfo", "mixed mode",
+                "environment", Array.of(
+                                    Map.of("key", "PATH",
+                                           "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                    Map.of("key", "XAUTHORITY",
+                                           "value", "/run/user/1000/gdm/Xauthority"),
+                                    Map.of("key", "GDMSESSION",
+                                           "value", "i3"),
+                                    Map.of("key", "fish_greeting",
+                                           "value", ""),
+                                    Map.of("key", "TERM",
+                                           "value", "xterm-256color"),
+                                    Map.of("key", "DARWIN_MODE",
+                                           "value", "0"),
+                                    Map.of("key", "LANG",
+                                           "value", "en_US.UTF-8"),
+                                    Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                           "value", "unix:path=/run/user/1000/bus"),
+                                    Map.of("key", "XDG_SESSION_ID",
+                                           "value", "2"),
+                                    Map.of("key", "XDG_SESSION_TYPE",
+                                           "value", "x11"),
+                                    Map.of("key", "XDG_CURRENT_DESKTOP",
+                                           "value", "i3"),
+                                    Map.of("key", "DISPLAY",
+                                           "value", ":0"),
+                                    Map.of("key", "CYGWIN_MODE",
+                                           "value", "0"),
+                                    Map.of("key", "COLORTERM",
+                                           "value", "truecolor"),
+                                    Map.of("key", "_",
+                                           "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                "javaVersion", "1.8.0_131",
+                "jvmVersion", "25.131-b12",
+                "jvmId", "jid1",
+                "javaCommandLine", "j cl",
+                "vmArguments", "-Djline.log.jul=true",
+                "jvmPid", 1,
+                "lastUpdated", Map.of("$numberLong", "333"),
+                "mainClass", "mc"),
+                Map.of("agentId", "aid",
+                        "startTime", Map.of("$numberLong", "1495727607481"),
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "uid", 1000,
+                        "jvmName", "vm",
+                        "stopTime", Map.of("$numberLong", "1495727607482"),
+                        "username", "user",
+                        "jvmInfo", "mixed mode",
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                                   "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "javaVersion", "1.8.0_131",
+                        "jvmVersion", "25.131-b12",
+                        "jvmId", "jid2",
+                        "javaCommandLine", "j cl",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmPid", 2,
+                        "lastUpdated", Map.of("$numberLong", "333"),
+                        "mainClass", "mc"));
 
-        private final String postDataWithSystemId = postData.substring(0, postData.length() - 2) +
-                ", \"systemId\" : \"invalid\"}]";
+    private final String postData = postDataWrapper.getJsonResponseArray();
+    private final String postDataWithSystemId = postData.substring(0, postData.length() - 2) + ", \"systemId\" : \"invalid\"}]";
 
     public JvmsServiceIntegrationTest() {
         super(jvmsUrl, "jvm-info");
     }
+
     @Test
     public void testGetEmpty() throws InterruptedException, TimeoutException, ExecutionException {
         String url = jvmsUrl + "/systems/1";
@@ -103,28 +175,63 @@
         String getUrl = jvmsUrl + "/systems/1/jvms/jid2";
 
         ContentResponse postResponse = client.newRequest(postUrl).method(HttpMethod.POST)
-                .content(new StringContentProvider(postData), "application/json").send();
+                .content(new StringContentProvider(postDataWrapper.getJsonResponseArray()), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
         ContentResponse getResponse = client.newRequest(getUrl).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
 
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
-                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\",\"javaHome\":" +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
-                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\"," +
-                "\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
-                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvmName", "vm",
+                        "agentId", "aid",
+                        "javaCommandLine", "j cl",
+                        "lastUpdated", 333,
+                        "javaVersion", "1.8.0_131",
+                        "jvmId", "jid2",
+                        "isAlive", false,
+                        "systemId", "1",
+                        "jvmPid", 2,
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "stopTime", 1495727607482L,
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmInfo", "mixed mode",
+                        "jvmVersion", "25.131-b12",
+                        "username", "user",
+                        "mainClass", "mc",
+                        "environment", Array.of(
+                                Map.of("key", "PATH",
+                                        "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                Map.of("key", "XAUTHORITY",
+                                        "value", "/run/user/1000/gdm/Xauthority"),
+                                Map.of("key", "GDMSESSION",
+                                        "value", "i3"),
+                                Map.of("key", "fish_greeting",
+                                        "value", ""),
+                                Map.of("key", "TERM",
+                                        "value", "xterm-256color"),
+                                Map.of("key", "DARWIN_MODE",
+                                        "value", "0"),
+                                Map.of("key", "LANG",
+                                        "value", "en_US.UTF-8"),
+                                Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                        "value", "unix:path=/run/user/1000/bus"),
+                                Map.of("key", "XDG_SESSION_ID",
+                                        "value", "2"),
+                                Map.of("key", "XDG_SESSION_TYPE",
+                                        "value", "x11"),
+                                Map.of("key", "XDG_CURRENT_DESKTOP",
+                                        "value", "i3"),
+                                Map.of("key", "DISPLAY",
+                                        "value", ":0"),
+                                Map.of("key", "CYGWIN_MODE",
+                                        "value", "0"),
+                                Map.of("key", "COLORTERM",
+                                        "value", "truecolor"),
+                                Map.of("key", "_",
+                                        "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "startTime", 1495727607481L,
+                        "uid", 1000));
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -139,27 +246,61 @@
         String query = "?aliveOnly=false&offset=1";
         ContentResponse response = client.newRequest(treeUrl + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", " +
-                "\"jvms\":[{ \"agentId\" : \"aid\", \"jvmId\" : \"jid2\", \"jvmPid\" : 2, " +
-                "\"startTime\" : { \"$numberLong\" : \"1495727607481\" }, " +
-                "\"stopTime\" : { \"$numberLong\" : \"1495727607482\" }, " +
-                "\"javaVersion\" : \"1.8.0_131\", " +
-                "\"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", " +
-                "\"mainClass\" : \"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", " +
-                "\"vmArguments\" : \"-Djline.log.jul=true\", \"jvmInfo\" : \"mixed mode\", " +
-                "\"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" : \"25.131-b12\", " +
-                "\"environment\" : [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, " +
-                "{ \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, " +
-                "{ \"key\" : \"GDMSESSION\", \"value\" : \"i3\" }, { \"key\" : \"fish_greeting\", \"value\" : \"\" }, " +
-                "{ \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, { \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, " +
-                "{ \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, " +
-                "{ \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }, " +
-                "{ \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, " +
-                "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
-                "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
-                "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : false }]}]}";
-        assertEquals(expected, response.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("systemId", "1",
+                        "jvms", Array.of(Map.of("jvmPid", 2,
+                        "uid", 1000,
+                        "jvmVersion", "25.131-b12",
+                        "javaVersion", "1.8.0_131",
+                        "lastUpdated", Map.of("$numberLong", "333"),
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmId", "jid2",
+                        "startTime", Map.of("$numberLong", "1495727607481"),
+                        "username", "user",
+                        "systemId", "1",
+                        "stopTime", Map.of("$numberLong", "1495727607482"),
+                        "environment", Array.of(
+                                           Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                                   "key", "PATH"),
+                                           Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                   "key", "XAUTHORITY"),
+                                           Map.of("value", "i3",
+                                                   "key", "GDMSESSION"),
+                                           Map.of("value", "",
+                                                   "key", "fish_greeting"),
+                                           Map.of("value", "xterm-256color",
+                                                   "key", "TERM"),
+                                           Map.of("value", "0",
+                                                   "key", "DARWIN_MODE"),
+                                           Map.of("value", "en_US.UTF-8",
+                                                   "key", "LANG"),
+                                           Map.of("value", "unix:path=/run/user/1000/bus",
+                                                   "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                           Map.of("value", "2",
+                                                   "key", "XDG_SESSION_ID"),
+                                           Map.of("value", "x11",
+                                                   "key", "XDG_SESSION_TYPE"),
+                                           Map.of("value", "i3",
+                                                   "key", "XDG_CURRENT_DESKTOP"),
+                                           Map.of("value", ":0",
+                                                   "key", "DISPLAY"),
+                                           Map.of("value", "0",
+                                                   "key", "CYGWIN_MODE"),
+                                           Map.of("value", "truecolor",
+                                                   "key", "COLORTERM"),
+                                           Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                   "key", "_")),
+                        "jvmInfo", "mixed mode",
+                        "jvmName", "vm",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "isAlive", false,
+                        "mainClass", "mc",
+                        "javaCommandLine", "j cl",
+                        "agentId", "aid")))
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
     }
 
     @Test
@@ -167,28 +308,67 @@
         String url = jvmsUrl + "/systems/1";
 
         ContentResponse postResponse = client.newRequest(url).method(HttpMethod.POST)
-                .content(new StringContentProvider(postData), "application/json").send();
+                .content(new StringContentProvider(postDataWrapper.getJsonResponseArray()), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
         String query = "/jvms/jid1";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
 
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1," +
-                "\"startTime\":1495727607481,\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":" +
-                "\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":" +
-                "\"25.131-b12\",\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
-                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\"," +
-                "\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"},{\"key\":\"DBUS_SESSION_BUS_ADDRESS\"," +
-                "\"value\":\"unix:path\\u003d/run/user/1000/bus\"},{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"}," +
-                "{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"}," +
-                "{\"key\":\"DISPLAY\",\"value\":\":0\"},{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\"," +
-                "\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "mainClass", "mc",
+                        "jvmId", "jid1",
+                        "lastUpdated", 333,
+                        "javaCommandLine", "j cl",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "isAlive", true,
+                        "uid", 1000,
+                        "username", "user",
+                        "jvmVersion", "25.131-b12",
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                                   "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "startTime", 1495727607481L,
+                        "jvmName", "vm",
+                        "jvmInfo", "mixed mode",
+                        "agentId", "aid",
+                        "systemId", "1",
+                        "javaVersion", "1.8.0_131",
+                        "stopTime", -9223372036854775808L,
+                        "jvmPid", 1)
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -196,28 +376,65 @@
         String url = jvmsUrl + "/systems/1";
 
         ContentResponse postResponse = client.newRequest(url).method(HttpMethod.POST)
-                .content(new StringContentProvider(postData), "application/json").send();
+                .content(new StringContentProvider(postDataWrapper.getJsonResponseArray()), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
         ContentResponse getResponse = client.newRequest(url).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1," +
-                "\"startTime\":1495727607481,\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\"," +
-                "\"vmArguments\":\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333," +
-                "\"jvmVersion\":\"25.131-b12\",\"environment\":[{\"key\":\"PATH\",\"value\":" +
-                "\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"},{\"key\":\"XAUTHORITY\",\"value\":" +
-                "\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
-                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
-                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvmName", "vm",
+                        "lastUpdated", 333,
+                        "stopTime", -9223372036854775808L,
+                        "mainClass", "mc",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmPid", 1,
+                        "uid", 1000,
+                        "jvmVersion", "25.131-b12",
+                        "javaVersion", "1.8.0_131",
+                        "startTime", 1495727607481L,
+                        "javaCommandLine", "j cl",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "username", "user",
+                        "agentId", "aid",
+                        "systemId", "1",
+                        "jvmId", "jid1",
+                        "environment", Array.of(
+                                           Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                                   "key", "PATH"),
+                                           Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                   "key", "XAUTHORITY"),
+                                           Map.of("value", "i3",
+                                                   "key", "GDMSESSION"),
+                                           Map.of("value", "",
+                                                   "key", "fish_greeting"),
+                                           Map.of("value", "xterm-256color",
+                                                   "key", "TERM"),
+                                           Map.of("value", "0",
+                                                   "key", "DARWIN_MODE"),
+                                           Map.of("value", "en_US.UTF-8",
+                                                   "key", "LANG"),
+                                           Map.of("value", "unix:path=/run/user/1000/bus",
+                                                   "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                           Map.of("value", "2",
+                                                   "key", "XDG_SESSION_ID"),
+                                           Map.of("value", "x11",
+                                                   "key", "XDG_SESSION_TYPE"),
+                                           Map.of("value", "i3",
+                                                   "key", "XDG_CURRENT_DESKTOP"),
+                                           Map.of("value", ":0",
+                                                   "key", "DISPLAY"),
+                                           Map.of("value", "0",
+                                                   "key", "CYGWIN_MODE"),
+                                           Map.of("value", "truecolor",
+                                                   "key", "COLORTERM"),
+                                           Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                   "key", "_")),
+                        "jvmInfo", "mixed mode",
+                        "isAlive", true)
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     /*
@@ -228,28 +445,64 @@
     public void testPostWithSystemId() throws InterruptedException, ExecutionException, TimeoutException {
         String url = jvmsUrl + "/systems/1";
 
+        // TODO - This should be using the ContentWrapper version of 'postDataWithSystemId'
         ContentResponse postResponse = client.newRequest(url).method(HttpMethod.POST)
                 .content(new StringContentProvider(postDataWithSystemId), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
         ContentResponse getResponse = client.newRequest(url).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1," +
-                "\"startTime\":1495727607481,\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
-                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
-                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
-                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("username", "user",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "stopTime", -9223372036854775808L,
+                        "jvmName", "vm",
+                        "lastUpdated", 333,
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "systemId", "1",
+                        "isAlive", true,
+                        "jvmId", "jid1",
+                        "javaVersion", "1.8.0_131",
+                        "javaCommandLine", "j cl",
+                        "jvmInfo", "mixed mode",
+                        "startTime", 1495727607481L,
+                        "mainClass", "mc",
+                        "jvmVersion", "25.131-b12",
+                        "agentId", "aid",
+                        "uid", 1000,
+                        "environment", Array.of(Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                "key", "PATH"),
+                                Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                        "key", "XAUTHORITY"),
+                                Map.of("value", "i3",
+                                        "key", "GDMSESSION"),
+                                Map.of("value", "",
+                                        "key", "fish_greeting"),
+                                Map.of("value", "xterm-256color",
+                                        "key", "TERM"),
+                                Map.of("value", "0",
+                                        "key", "DARWIN_MODE"),
+                                Map.of("value", "en_US.UTF-8",
+                                        "key", "LANG"),
+                                Map.of("value", "unix:path=/run/user/1000/bus",
+                                        "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                Map.of("value", "2",
+                                        "key", "XDG_SESSION_ID"),
+                                Map.of("value", "x11",
+                                        "key", "XDG_SESSION_TYPE"),
+                                Map.of("value", "i3",
+                                        "key", "XDG_CURRENT_DESKTOP"),
+                                Map.of("value", ":0",
+                                        "key", "DISPLAY"),
+                                Map.of("value", "0",
+                                        "key", "CYGWIN_MODE"),
+                                Map.of("value", "truecolor",
+                                        "key", "COLORTERM"),
+                                Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                        "key", "_")),
+                        "jvmPid", 1));
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -264,40 +517,108 @@
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
 
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("mainClass", "mc",
+                        "username", "user",
+                        "systemId", "1",
+                        "jvmId", "jid1",
+                        "javaVersion", "1.8.0_131",
+                        "agentId", "aid",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmVersion", "25.131-b12",
+                        "lastUpdated", 333,
+                        "uid", 1000,
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                                   "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "isAlive", true,
+                        "javaCommandLine", "j cl",
+                        "jvmPid", 1,
+                        "jvmName", "vm",
+                        "jvmInfo", "mixed mode",
+                        "stopTime", -9223372036854775808L,
+                        "startTime", 1495727607481L),
+                Map.of("mainClass", "mc",
+                        "username", "user",
+                        "systemId", "1",
+                        "jvmId", "jid2",
+                        "javaVersion", "1.8.0_131",
+                        "agentId", "aid",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmVersion", "25.131-b12",
+                        "lastUpdated", 333,
+                        "uid", 1000,
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                                   "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "isAlive", false,
+                        "javaCommandLine", "j cl",
+                        "jvmPid", 2,
+                        "jvmName", "vm",
+                        "jvmInfo", "mixed mode",
+                        "stopTime", 1495727607482L,
+                        "startTime", 1495727607481L)
 
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1," +
-                "\"startTime\":1495727607481,\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\"," +
-                "\"vmArguments\":\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\"," +
-                "\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\"," +
-                "\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
-                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true},{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
-                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
-                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\",\"environment\":" +
-                "[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"}," +
-                "{\"key\":\"GDMSESSION\",\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"}," +
-                "{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\",\"value\":\"0\"}," +
-                "{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
-
-        assertEquals(expected, getResponse.getContentAsString());
+        );
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -311,23 +632,61 @@
         String query = "?offset=1";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
-                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\"," +
-                "\"vmArguments\":\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"}," +
-                "{\"key\":\"GDMSESSION\",\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"}," +
-                "{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\",\"value\":\"0\"}," +
-                "{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}" +
-                ",{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("environment", Array.of(
+                                               Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                                       "key", "PATH"),
+                                               Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                       "key", "XAUTHORITY"),
+                                               Map.of("value", "i3",
+                                                       "key", "GDMSESSION"),
+                                               Map.of("value", "",
+                                                       "key", "fish_greeting"),
+                                               Map.of("value", "xterm-256color",
+                                                       "key", "TERM"),
+                                               Map.of("value", "0",
+                                                       "key", "DARWIN_MODE"),
+                                               Map.of("value", "en_US.UTF-8",
+                                                       "key", "LANG"),
+                                               Map.of("value", "unix:path=/run/user/1000/bus",
+                                                       "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                               Map.of("value", "2",
+                                                       "key", "XDG_SESSION_ID"),
+                                               Map.of("value", "x11",
+                                                       "key", "XDG_SESSION_TYPE"),
+                                               Map.of("value", "i3",
+                                                       "key", "XDG_CURRENT_DESKTOP"),
+                                               Map.of("value", ":0",
+                                                       "key", "DISPLAY"),
+                                               Map.of("value", "0",
+                                                       "key", "CYGWIN_MODE"),
+                                               Map.of("value", "truecolor",
+                                                       "key", "COLORTERM"),
+                                               Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                       "key", "_")),
+                        "javaCommandLine", "j cl",
+                        "jvmName", "vm",
+                        "mainClass", "mc",
+                        "jvmPid", 2,
+                        "lastUpdated", 333,
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "jvmInfo", "mixed mode",
+                        "startTime", 1495727607481L,
+                        "vmArguments", "-Djline.log.jul=true",
+                        "uid", 1000,
+                        "jvmId", "jid2",
+                        "agentId", "aid",
+                        "systemId", "1",
+                        "stopTime", 1495727607482L,
+                        "isAlive", false,
+                        "javaVersion", "1.8.0_131",
+                        "username", "user",
+                        "jvmVersion", "25.131-b12")
+
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -341,22 +700,60 @@
         String query = "?query=jvmId==jid2";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
-                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":" +
-                "\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":" +
-                "\"25.131-b12\",\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
-                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\"," +
-                "\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"},{\"key\":\"DBUS_SESSION_BUS_ADDRESS\"," +
-                "\"value\":\"unix:path\\u003d/run/user/1000/bus\"},{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"}," +
-                "{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"}," +
-                "{\"key\":\"DISPLAY\",\"value\":\":0\"},{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\"," +
-                "\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
 
-        assertEquals(expected, getResponse.getContentAsString());
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("startTime", 1495727607481L,
+                        "jvmPid", 2,
+                        "javaCommandLine", "j cl",
+                        "jvmName", "vm",
+                        "lastUpdated", 333,
+                        "stopTime", 1495727607482L,
+                        "mainClass", "mc",
+                        "javaVersion", "1.8.0_131",
+                        "jvmVersion", "25.131-b12",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "jvmInfo", "mixed mode",
+                        "username", "user",
+                        "isAlive", false,
+                        "systemId", "1",
+                        "jvmId", "jid2",
+                        "uid", 1000,
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                               "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "vmArguments", "-Djline.log.jul=true",
+                        "agentId", "aid")
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -370,22 +767,60 @@
         String query = "/jvms/jid2";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
-                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\"," +
-                "\"mainClass\":\"mc\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":" +
-                "\"-Djline.log.jul\\u003dtrue\",\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":" +
-                "\"25.131-b12\",\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
-                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\"," +
-                "\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"},{\"key\":\"DBUS_SESSION_BUS_ADDRESS\"," +
-                "\"value\":\"unix:path\\u003d/run/user/1000/bus\"},{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"}," +
-                "{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"}," +
-                "{\"key\":\"DISPLAY\",\"value\":\":0\"},{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\"," +
-                "\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
 
-        assertEquals(expected, getResponse.getContentAsString());
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "agentId", "aid",
+                        "startTime", 1495727607481L,
+                        "mainClass", "mc",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "javaVersion", "1.8.0_131",
+                        "jvmId", "jid2",
+                        "systemId", "1",
+                        "jvmInfo", "mixed mode",
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                                   "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "jvmName", "vm",
+                        "javaCommandLine", "j cl",
+                        "isAlive", false,
+                        "jvmVersion", "25.131-b12",
+                        "jvmPid", 2,
+                        "username", "user",
+                        "stopTime", 1495727607482L,
+                        "lastUpdated", 333,
+                        "uid", 1000)
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -399,8 +834,11 @@
         String query = "?include=agentId,jvmId";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("agentId", "aid", "jvmId", "jid1", "isAlive", true)
+        );
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -414,22 +852,59 @@
         String query = "?exclude=agentId";
         ContentResponse getResponse = client.newRequest(url + query).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"jvmId\":\"jid1\",\"jvmPid\":1,\"startTime\":1495727607481," +
-                "\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\",\"javaHome\":" +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
-                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\",\"environment\":" +
-                "[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\"," +
-                "\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":" +
-                "\"xterm-256color\"},{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":" +
-                "\"en_US.UTF-8\"},{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvmPid", 1,
+                        "javaVersion", "1.8.0_131",
+                        "environment", Array.of(
+                                           Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                               "key", "PATH"),
+                                           Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                   "key", "XAUTHORITY"),
+                                           Map.of("value", "i3",
+                                                   "key", "GDMSESSION"),
+                                           Map.of("value", "",
+                                                   "key", "fish_greeting"),
+                                           Map.of("value", "xterm-256color",
+                                                   "key", "TERM"),
+                                           Map.of("value", "0",
+                                                   "key", "DARWIN_MODE"),
+                                           Map.of("value", "en_US.UTF-8",
+                                                   "key", "LANG"),
+                                           Map.of("value", "unix:path=/run/user/1000/bus",
+                                                   "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                           Map.of("value", "2",
+                                                   "key", "XDG_SESSION_ID"),
+                                           Map.of("value", "x11",
+                                                   "key", "XDG_SESSION_TYPE"),
+                                           Map.of("value", "i3",
+                                                   "key", "XDG_CURRENT_DESKTOP"),
+                                           Map.of("value", ":0",
+                                                   "key", "DISPLAY"),
+                                           Map.of("value", "0",
+                                                   "key", "CYGWIN_MODE"),
+                                           Map.of("value", "truecolor",
+                                                   "key", "COLORTERM"),
+                                           Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                   "key", "_")),
+                        "isAlive", true,
+                        "uid", 1000,
+                        "systemId", "1",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "jvmVersion", "25.131-b12",
+                        "stopTime", -9223372036854775808L,
+                        "jvmId", "jid1",
+                        "jvmName", "vm",
+                        "jvmInfo", "mixed mode",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "mainClass", "mc",
+                        "startTime", 1495727607481L,
+                        "lastUpdated", 333,
+                        "username", "user",
+                        "javaCommandLine", "j cl")
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -445,7 +920,7 @@
 
         ContentResponse getResponse = client.newRequest(url).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[]}";
+        String expected = HttpTestUtil.EMPTY_RESPONSE;
         assertEquals(expected, getResponse.getContentAsString());
     }
 
@@ -458,29 +933,68 @@
                 .content(new StringContentProvider(postData), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
-        String setContent = "{\"set\":{\"mainClass\":\"hello\",\"javaVersion\":\"1.7.0\"}}";
+        ResponseSetWrapper responseSetWrapper = new ResponseSetWrapper().key("mainClass").value("hello")
+                                                                       .key("javaVersion").value("1.7.0");
         ContentResponse putResponse = client.newRequest(putUrl).method(HttpMethod.PUT).
-                content(new StringContentProvider(setContent), "application/json").send();
+                content(new StringContentProvider(responseSetWrapper.toSetString()), "application/json").send();
         assertEquals(200, putResponse.getStatus());
 
         ContentResponse getResponse = client.newRequest(url).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1," +
-                "\"startTime\":1495727607481,\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.7.0\"," +
-                "\"javaHome\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":" +
-                "\"hello\",\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\"," +
-                "\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
-                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvmName", "vm",
+                        "username", "user",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "javaCommandLine", "j cl",
+                        "agentId", "aid",
+                        "jvmId", "jid1",
+                        "environment", Array.of(
+                                           Map.of("key", "PATH",
+                                               "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                           Map.of("key", "XAUTHORITY",
+                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                           Map.of("key", "GDMSESSION",
+                                                   "value", "i3"),
+                                           Map.of("key", "fish_greeting",
+                                                   "value", ""),
+                                           Map.of("key", "TERM",
+                                                   "value", "xterm-256color"),
+                                           Map.of("key", "DARWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "LANG",
+                                                   "value", "en_US.UTF-8"),
+                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                   "value", "unix:path=/run/user/1000/bus"),
+                                           Map.of("key", "XDG_SESSION_ID",
+                                                   "value", "2"),
+                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                   "value", "x11"),
+                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                   "value", "i3"),
+                                           Map.of("key", "DISPLAY",
+                                                   "value", ":0"),
+                                           Map.of("key", "CYGWIN_MODE",
+                                                   "value", "0"),
+                                           Map.of("key", "COLORTERM",
+                                                   "value", "truecolor"),
+                                           Map.of("key", "_",
+                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                        "mainClass", "hello",
+                        "uid", 1000,
+                        "systemId", "1",
+                        "stopTime", -9223372036854775808L,
+                        "jvmInfo", "mixed mode",
+                        "jvmVersion", "25.131-b12",
+                        "lastUpdated", 333,
+                        "startTime", 1495727607481L,
+                        "jvmPid", 1,
+                        "vmArguments", "-Djline.log.jul=true",
+                        "javaVersion", "1.7.0",
+                        "isAlive", true)
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     /*
@@ -488,7 +1002,6 @@
      */
     @Test
     public void testPutInvalidField() throws InterruptedException, TimeoutException, ExecutionException {
-        //
         String url = jvmsUrl + "/systems/1";
         String putUrl = jvmsUrl + "/systems/1/jvms/jid1";
 
@@ -496,32 +1009,72 @@
                 .content(new StringContentProvider(postData), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
-        String setContent = "{\"set\":{\"systemId\":\"hello\"}}";
+        ResponseSetWrapper responseSetWrapper = new ResponseSetWrapper().key("systemId").value("hello");
         ContentResponse putResponse = client.newRequest(putUrl).method(HttpMethod.PUT)
-                .content(new StringContentProvider(setContent), "application/json").send();
+                .content(new StringContentProvider(responseSetWrapper.toSetString()), "application/json").send();
         assertEquals(400, putResponse.getStatus());
 
-        setContent = "{\"set\":{\"jvmId\":\"hello\"}}";
+        responseSetWrapper = new ResponseSetWrapper().key("jvmId").value("hello");
         putResponse = client.newRequest(putUrl).method(HttpMethod.PUT)
-                .content(new StringContentProvider(setContent), "application/json").send();
+                .content(new StringContentProvider(responseSetWrapper.toSetString()), "application/json").send();
         assertEquals(400, putResponse.getStatus());
 
         ContentResponse getResponse = client.newRequest(url).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid1\",\"jvmPid\":1,\"startTime\":1495727607481," +
-                "\"stopTime\":-9223372036854775808,\"javaVersion\":\"1.8.0_131\",\"javaHome\":" +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
-                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\",\"value\":\"i3\"}," +
-                "{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"},{\"key\":\"DARWIN_MODE\"," +
-                "\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"},{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":" +
-                "\"unix:path\\u003d/run/user/1000/bus\"},{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\"," +
-                "\"value\":\"x11\"},{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"},{\"key\":\"_\",\"value\":" +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}],\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":true}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvmId", "jid1",
+                        "environment", Array.of(
+                                           Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                               "key", "PATH"),
+                                           Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                   "key", "XAUTHORITY"),
+                                           Map.of("value", "i3",
+                                                   "key", "GDMSESSION"),
+                                           Map.of("value", "",
+                                                   "key", "fish_greeting"),
+                                           Map.of("value", "xterm-256color",
+                                                   "key", "TERM"),
+                                           Map.of("value", "0",
+                                                   "key", "DARWIN_MODE"),
+                                           Map.of("value", "en_US.UTF-8",
+                                                   "key", "LANG"),
+                                           Map.of("value", "unix:path=/run/user/1000/bus",
+                                                   "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                           Map.of("value", "2",
+                                                   "key", "XDG_SESSION_ID"),
+                                           Map.of("value", "x11",
+                                                   "key", "XDG_SESSION_TYPE"),
+                                           Map.of("value", "i3",
+                                                   "key", "XDG_CURRENT_DESKTOP"),
+                                           Map.of("value", ":0",
+                                                   "key", "DISPLAY"),
+                                           Map.of("value", "0",
+                                                   "key", "CYGWIN_MODE"),
+                                           Map.of("value", "truecolor",
+                                                   "key", "COLORTERM"),
+                                           Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                   "key", "_")),
+                        "stopTime", -9223372036854775808L,
+                        "lastUpdated", 333,
+                        "systemId", "1",
+                        "uid", 1000,
+                        "username", "user",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "mainClass", "mc",
+                        "jvmPid", 1,
+                        "jvmVersion", "25.131-b12",
+                        "jvmName", "vm",
+                        "javaCommandLine", "j cl",
+                        "isAlive", true,
+                        "javaVersion", "1.8.0_131",
+                        "jvmInfo", "mixed mode",
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "startTime", 1495727607481L,
+                        "agentId", "aid")
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -538,22 +1091,61 @@
 
         ContentResponse getResponse = client.newRequest(url).method(HttpMethod.GET).send();
         assertEquals(200, getResponse.getStatus());
-        String expected = "{\"response\":[{\"agentId\":\"aid\",\"jvmId\":\"jid2\",\"jvmPid\":2," +
-                "\"startTime\":1495727607481,\"stopTime\":1495727607482,\"javaVersion\":\"1.8.0_131\",\"javaHome\":" +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\",\"mainClass\":\"mc\"," +
-                "\"javaCommandLine\":\"j cl\",\"jvmName\":\"vm\",\"vmArguments\":\"-Djline.log.jul\\u003dtrue\"," +
-                "\"jvmInfo\":\"mixed mode\",\"lastUpdated\":333,\"jvmVersion\":\"25.131-b12\"," +
-                "\"environment\":[{\"key\":\"PATH\",\"value\":\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\"}," +
-                "{\"key\":\"XAUTHORITY\",\"value\":\"/run/user/1000/gdm/Xauthority\"},{\"key\":\"GDMSESSION\"," +
-                "\"value\":\"i3\"},{\"key\":\"fish_greeting\",\"value\":\"\"},{\"key\":\"TERM\",\"value\":\"xterm-256color\"}," +
-                "{\"key\":\"DARWIN_MODE\",\"value\":\"0\"},{\"key\":\"LANG\",\"value\":\"en_US.UTF-8\"}," +
-                "{\"key\":\"DBUS_SESSION_BUS_ADDRESS\",\"value\":\"unix:path\\u003d/run/user/1000/bus\"}," +
-                "{\"key\":\"XDG_SESSION_ID\",\"value\":\"2\"},{\"key\":\"XDG_SESSION_TYPE\",\"value\":\"x11\"}," +
-                "{\"key\":\"XDG_CURRENT_DESKTOP\",\"value\":\"i3\"},{\"key\":\"DISPLAY\",\"value\":\":0\"}," +
-                "{\"key\":\"CYGWIN_MODE\",\"value\":\"0\"},{\"key\":\"COLORTERM\",\"value\":\"truecolor\"}," +
-                "{\"key\":\"_\",\"value\":\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\"}]," +
-                "\"uid\":1000,\"username\":\"user\",\"systemId\":\"1\",\"isAlive\":false}]}";
-        assertEquals(expected, getResponse.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("environment", Array.of(
+                                                   Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                                       "key", "PATH"),
+                                                   Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                           "key", "XAUTHORITY"),
+                                                   Map.of("value", "i3",
+                                                           "key", "GDMSESSION"),
+                                                   Map.of("value", "",
+                                                           "key", "fish_greeting"),
+                                                   Map.of("value", "xterm-256color",
+                                                           "key", "TERM"),
+                                                   Map.of("value", "0",
+                                                           "key", "DARWIN_MODE"),
+                                                   Map.of("value", "en_US.UTF-8",
+                                                           "key", "LANG"),
+                                                   Map.of("value", "unix:path=/run/user/1000/bus",
+                                                           "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                                   Map.of("value", "2",
+                                                           "key", "XDG_SESSION_ID"),
+                                                   Map.of("value", "x11",
+                                                           "key", "XDG_SESSION_TYPE"),
+                                                   Map.of("value", "i3",
+                                                           "key", "XDG_CURRENT_DESKTOP"),
+                                                   Map.of("value", ":0",
+                                                           "key", "DISPLAY"),
+                                                   Map.of("value", "0",
+                                                           "key", "CYGWIN_MODE"),
+                                                   Map.of("value", "truecolor",
+                                                           "key", "COLORTERM"),
+                                                   Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                           "key", "_")),
+                        "systemId", "1",
+                        "uid", 1000,
+                        "username", "user",
+                        "javaCommandLine", "j cl",
+                        "isAlive", false,
+                        "startTime", 1495727607481L,
+                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                        "stopTime", 1495727607482L,
+                        "mainClass", "mc",
+                        "jvmId", "jid2",
+                        "agentId", "aid",
+                        "javaVersion", "1.8.0_131",
+                        "lastUpdated", 333,
+                        "jvmPid", 2,
+                        "jvmName", "vm",
+                        "vmArguments", "-Djline.log.jul=true",
+                        "jvmVersion", "25.131-b12",
+                        "jvmInfo", "mixed mode")
+
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(getResponse.getContentAsString());
     }
 
     @Test
@@ -565,16 +1157,16 @@
                 .content(new StringContentProvider(postData), "application/json").send();
         assertEquals(200, postResponse.getStatus());
 
-
         ContentResponse updateResponse = client.newRequest(updateUrl).method(HttpMethod.PUT).send();
         assertEquals(200, updateResponse.getStatus());
 
         ContentResponse response = client.newRequest(url).method(HttpMethod.GET)
                 .param("include", "lastUpdated").send();
         assertEquals(200, response.getStatus());
-        String expected = "{\"response\":[{\"lastUpdated\":2000,\"isAlive\":true}]}";
-        assertEquals(expected, response.getContentAsString());
 
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("lastUpdated", 2000, "isAlive", true));
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
     }
 
     @Test
@@ -588,25 +1180,61 @@
 
         ContentResponse response = client.newRequest(treeUrl).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", \"jvms\":[{ \"agentId\" : \"aid\", \"jvmId\" : " +
-                "\"jid1\", \"jvmPid\" : 1, \"startTime\" : { \"$numberLong\" : \"1495727607481\" }, \"stopTime\" : " +
-                "{ \"$numberLong\" : \"-9223372036854775808\" }, \"javaVersion\" : \"1.8.0_131\", \"javaHome\" : " +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", \"mainClass\" : " +
-                "\"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", \"vmArguments\" : " +
-                "\"-Djline.log.jul=true\", \"jvmInfo\" : \"mixed mode\", \"lastUpdated\" : " +
-                "{ \"$numberLong\" : \"333\" }, \"jvmVersion\" : \"25.131-b12\", \"environment\" : " +
-                "[{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, " +
-                "{ \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, { \"key\" : " +
-                "\"GDMSESSION\", \"value\" : \"i3\" }, { \"key\" : \"fish_greeting\", \"value\" : \"\" }, " +
-                "{ \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, { \"key\" : \"DARWIN_MODE\", \"value\" : " +
-                "\"0\" }, { \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, { \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", " +
-                "\"value\" : \"unix:path=/run/user/1000/bus\" }, { \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, " +
-                "{ \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, { \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : " +
-                "\"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, { \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, " +
-                "{ \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, { \"key\" : \"_\", \"value\" : " +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], \"uid\" : " +
-                "1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : true }]}]}";
-        assertEquals(expected, response.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("systemId", "1",
+                        "jvms", Array.of(
+                                        Map.of("environment", Array.of(Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                               "key", "PATH"),
+                                        Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                               "key", "XAUTHORITY"),
+                                        Map.of("value", "i3",
+                                               "key", "GDMSESSION"),
+                                        Map.of("value", "",
+                                               "key", "fish_greeting"),
+                                        Map.of("value", "xterm-256color",
+                                               "key", "TERM"),
+                                        Map.of("value", "0",
+                                               "key", "DARWIN_MODE"),
+                                        Map.of("value", "en_US.UTF-8",
+                                               "key", "LANG"),
+                                        Map.of("value", "unix:path=/run/user/1000/bus",
+                                               "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                        Map.of("value", "2",
+                                               "key", "XDG_SESSION_ID"),
+                                        Map.of("value", "x11",
+                                               "key", "XDG_SESSION_TYPE"),
+                                        Map.of("value", "i3",
+                                               "key", "XDG_CURRENT_DESKTOP"),
+                                        Map.of("value", ":0",
+                                               "key", "DISPLAY"),
+                                        Map.of("value", "0",
+                                               "key", "CYGWIN_MODE"),
+                                        Map.of("value", "truecolor",
+                                               "key", "COLORTERM"),
+                                        Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                               "key", "_")),
+                                "jvmName", "vm",
+                                "stopTime", Map.of("$numberLong", "-9223372036854775808"),
+                                "startTime", Map.of("$numberLong", "1495727607481"),
+                                "javaVersion", "1.8.0_131",
+                                "lastUpdated", Map.of("$numberLong", "333"),
+                                "javaCommandLine", "j cl",
+                                "username", "user",
+                                "vmArguments", "-Djline.log.jul=true",
+                                "mainClass", "mc",
+                                "agentId", "aid",
+                                "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                                "jvmVersion", "25.131-b12",
+                                "isAlive", true,
+                                "systemId", "1",
+                                "jvmId", "jid1",
+                                "jvmInfo", "mixed mode",
+                                "jvmPid", 1,
+                                "uid", 1000)))
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
     }
 
     @Test
@@ -621,8 +1249,14 @@
         String query = "?include=jvmId";
         ContentResponse response = client.newRequest(treeUrl + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", \"jvms\":[{ \"jvmId\" : \"jid1\", \"isAlive\" : true }]}]}";
-        assertEquals(expected, response.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvms", Array.of(
+                        Map.of("jvmId", "jid1",
+                                "isAlive", true)),
+                                "systemId", "1")
+        );
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
     }
 
     @Test
@@ -637,24 +1271,60 @@
         String query = "?exclude=systemId";
         ContentResponse response = client.newRequest(treeUrl + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", \"jvms\":[{ \"agentId\" : \"aid\", " +
-                "\"jvmId\" : \"jid1\", \"jvmPid\" : 1, \"startTime\" : { \"$numberLong\" : \"1495727607481\" }, " +
-                "\"stopTime\" : { \"$numberLong\" : \"-9223372036854775808\" }, \"javaVersion\" : \"1.8.0_131\", " +
-                "\"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", \"mainClass\" : " +
-                "\"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", \"vmArguments\" : \"-Djline.log.jul=true\", " +
-                "\"jvmInfo\" : \"mixed mode\", \"lastUpdated\" : { \"$numberLong\" : \"333\" }, " +
-                "\"jvmVersion\" : \"25.131-b12\", \"environment\" : [{ \"key\" : \"PATH\", \"value\" : " +
-                "\"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, { \"key\" : \"XAUTHORITY\", \"value\" : " +
-                "\"/run/user/1000/gdm/Xauthority\" }, { \"key\" : \"GDMSESSION\", \"value\" : \"i3\" }, " +
-                "{ \"key\" : \"fish_greeting\", \"value\" : \"\" }, { \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, " +
-                "{ \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, " +
-                "{ \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }, " +
-                "{ \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, " +
-                "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
-                "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
-                "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"isAlive\" : true }]}]}";
-        assertEquals(expected, response.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("systemId", "1",
+                        "jvms", Array.of(Map.of("jvmId", "jid1",
+                                "jvmName", "vm",
+                                "username", "user",
+                                "startTime", Map.of("$numberLong", "1495727607481"),
+                                "mainClass", "mc",
+                                "uid", 1000,
+                                "isAlive", true,
+                                "vmArguments", "-Djline.log.jul=true",
+                                "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                                "javaCommandLine", "j cl",
+                                "environment", Array.of(
+                                                   Map.of("value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
+                                                           "key", "PATH"),
+                                                   Map.of("value", "/run/user/1000/gdm/Xauthority",
+                                                           "key", "XAUTHORITY"),
+                                                   Map.of("value", "i3",
+                                                           "key", "GDMSESSION"),
+                                                   Map.of("value", "",
+                                                           "key", "fish_greeting"),
+                                                   Map.of("value", "xterm-256color",
+                                                           "key", "TERM"),
+                                                   Map.of("value", "0",
+                                                           "key", "DARWIN_MODE"),
+                                                   Map.of("value", "en_US.UTF-8",
+                                                           "key", "LANG"),
+                                                   Map.of("value", "unix:path=/run/user/1000/bus",
+                                                           "key", "DBUS_SESSION_BUS_ADDRESS"),
+                                                   Map.of("value", "2",
+                                                           "key", "XDG_SESSION_ID"),
+                                                   Map.of("value", "x11",
+                                                           "key", "XDG_SESSION_TYPE"),
+                                                   Map.of("value", "i3",
+                                                           "key", "XDG_CURRENT_DESKTOP"),
+                                                   Map.of("value", ":0",
+                                                           "key", "DISPLAY"),
+                                                   Map.of("value", "0",
+                                                           "key", "CYGWIN_MODE"),
+                                                   Map.of("value", "truecolor",
+                                                           "key", "COLORTERM"),
+                                                   Map.of("value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java",
+                                                           "key", "_")),
+                                "javaVersion", "1.8.0_131",
+                                "jvmInfo", "mixed mode",
+                                "jvmPid", 1,
+                                "stopTime", Map.of("$numberLong", "-9223372036854775808"),
+                                "jvmVersion", "25.131-b12",
+                                "lastUpdated", Map.of("$numberLong", "333"),
+                                "agentId", "aid")))
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
     }
 
     @Test
@@ -669,44 +1339,115 @@
         String query = "?aliveOnly=false&limit=2";
         ContentResponse response = client.newRequest(treeUrl + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", \"jvms\":[{ \"agentId\" : \"aid\", \"jvmId\" : " +
-                "\"jid1\", \"jvmPid\" : 1, \"startTime\" : { \"$numberLong\" : \"1495727607481\" }, \"stopTime\" : " +
-                "{ \"$numberLong\" : \"-9223372036854775808\" }, \"javaVersion\" : \"1.8.0_131\", \"javaHome\" : " +
-                "\"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", \"mainClass\" : \"mc\", " +
-                "\"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", \"vmArguments\" : \"-Djline.log.jul=true\", " +
-                "\"jvmInfo\" : \"mixed mode\", \"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" : " +
-                "\"25.131-b12\", \"environment\" : [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, " +
-                "{ \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, { \"key\" : \"GDMSESSION\", \"value\" : \"i3\" }, " +
-                "{ \"key\" : \"fish_greeting\", \"value\" : \"\" }, { \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, " +
-                "{ \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, " +
-                "{ \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }, " +
-                "{ \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, " +
-                "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
-                "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
-                "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : true }," +
-                "{ \"agentId\" : \"aid\", \"jvmId\" : \"jid2\", \"jvmPid\" : 2, \"startTime\" : " +
-                "{ \"$numberLong\" : \"1495727607481\" }, \"stopTime\" : { \"$numberLong\" : \"1495727607482\" }, " +
-                "\"javaVersion\" : \"1.8.0_131\", \"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", " +
-                "\"mainClass\" : \"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", \"vmArguments\" : \"-Djline.log.jul=true\", " +
-                "\"jvmInfo\" : \"mixed mode\", \"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" : \"25.131-b12\", \"environment\" " +
-                ": [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, { \"key\" : \"XAUTHORITY\", " +
-                "\"value\" : \"/run/user/1000/gdm/Xauthority\" }, { \"key\" : \"GDMSESSION\", \"value\" : \"i3\" }, " +
-                "{ \"key\" : \"fish_greeting\", \"value\" : \"\" }, { \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, " +
-                "{ \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, " +
-                "{ \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }, " +
-                "{ \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, " +
-                "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
-                "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
-                "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : false }]}]}";
-        assertEquals(expected, response.getContentAsString());
+
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("systemId", "1",
+                        "jvms", Array.of(Map.of("mainClass", "mc",
+                                "uid", 1000,
+                                "agentId", "aid",
+                                "environment", Array.of(
+                                                   Map.of("key", "PATH",
+                                                       "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                                   Map.of("key", "XAUTHORITY",
+                                                           "value", "/run/user/1000/gdm/Xauthority"),
+                                                   Map.of("key", "GDMSESSION",
+                                                           "value", "i3"),
+                                                   Map.of("key", "fish_greeting",
+                                                           "value", ""),
+                                                   Map.of("key", "TERM",
+                                                           "value", "xterm-256color"),
+                                                   Map.of("key", "DARWIN_MODE",
+                                                           "value", "0"),
+                                                   Map.of("key", "LANG",
+                                                           "value", "en_US.UTF-8"),
+                                                   Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                           "value", "unix:path=/run/user/1000/bus"),
+                                                   Map.of("key", "XDG_SESSION_ID",
+                                                           "value", "2"),
+                                                   Map.of("key", "XDG_SESSION_TYPE",
+                                                           "value", "x11"),
+                                                   Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                           "value", "i3"),
+                                                   Map.of("key", "DISPLAY",
+                                                           "value", ":0"),
+                                                   Map.of("key", "CYGWIN_MODE",
+                                                           "value", "0"),
+                                                   Map.of("key", "COLORTERM",
+                                                           "value", "truecolor"),
+                                                   Map.of("key", "_",
+                                                           "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                                "jvmId", "jid1",
+                                "javaVersion", "1.8.0_131",
+                                "javaCommandLine", "j cl",
+                                "jvmPid", 1,
+                                "jvmInfo", "mixed mode",
+                                "systemId", "1",
+                                "isAlive", true,
+                                "jvmName", "vm",
+                                "startTime", Map.of("$numberLong", "1495727607481"),
+                                "stopTime", Map.of("$numberLong", "-9223372036854775808"),
+                                "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                                "vmArguments", "-Djline.log.jul=true",
+                                "jvmVersion", "25.131-b12",
+                                "lastUpdated", Map.of("$numberLong", "333"),
+                                "username", "user"),
+                                Map.of("mainClass", "mc",
+                                        "uid", 1000,
+                                        "agentId", "aid",
+                                        "environment", Array.of(
+                                                           Map.of("key", "PATH",
+                                                               "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                                           Map.of("key", "XAUTHORITY",
+                                                                   "value", "/run/user/1000/gdm/Xauthority"),
+                                                           Map.of("key", "GDMSESSION",
+                                                                   "value", "i3"),
+                                                           Map.of("key", "fish_greeting",
+                                                                   "value", ""),
+                                                           Map.of("key", "TERM",
+                                                                   "value", "xterm-256color"),
+                                                           Map.of("key", "DARWIN_MODE",
+                                                                   "value", "0"),
+                                                           Map.of("key", "LANG",
+                                                                   "value", "en_US.UTF-8"),
+                                                           Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                                   "value", "unix:path=/run/user/1000/bus"),
+                                                           Map.of("key", "XDG_SESSION_ID",
+                                                                   "value", "2"),
+                                                           Map.of("key", "XDG_SESSION_TYPE",
+                                                                   "value", "x11"),
+                                                           Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                                   "value", "i3"),
+                                                           Map.of("key", "DISPLAY",
+                                                                   "value", ":0"),
+                                                           Map.of("key", "CYGWIN_MODE",
+                                                                   "value", "0"),
+                                                           Map.of("key", "COLORTERM",
+                                                                   "value", "truecolor"),
+                                                           Map.of("key", "_",
+                                                                   "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                                        "jvmId", "jid2",
+                                        "javaVersion", "1.8.0_131",
+                                        "javaCommandLine", "j cl",
+                                        "jvmPid", 2,
+                                        "jvmInfo", "mixed mode",
+                                        "systemId", "1",
+                                        "isAlive", false,
+                                        "jvmName", "vm",
+                                        "startTime", Map.of("$numberLong", "1495727607481"),
+                                        "stopTime", Map.of("$numberLong", "1495727607482"),
+                                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                                        "vmArguments", "-Djline.log.jul=true",
+                                        "jvmVersion", "25.131-b12",
+                                        "lastUpdated", Map.of("$numberLong", "333"),
+                                        "username", "user")))
+        );
+
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
     }
 
     @Test
     public void testTreeVersions() throws InterruptedException, TimeoutException, ExecutionException {
         String postUrl = jvmsUrl + "/systems/1";
-        String treeUrl = jvmsUrl + "/tree";
 
         ContentResponse postResponse = client.newRequest(postUrl).method(HttpMethod.POST)
                 .content(new StringContentProvider(postData), "application/json").send();
@@ -714,37 +1455,70 @@
 
         String query = "?aliveOnly=false&offset=1";
 
-        String expected = "{ \"response\" : [{\"systemId\":\"1\", " +
-                "\"jvms\":[{ \"agentId\" : \"aid\", \"jvmId\" : \"jid2\", \"jvmPid\" : 2, " +
-                "\"startTime\" : { \"$numberLong\" : \"1495727607481\" }, " +
-                "\"stopTime\" : { \"$numberLong\" : \"1495727607482\" }, " +
-                "\"javaVersion\" : \"1.8.0_131\", " +
-                "\"javaHome\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre\", " +
-                "\"mainClass\" : \"mc\", \"javaCommandLine\" : \"j cl\", \"jvmName\" : \"vm\", " +
-                "\"vmArguments\" : \"-Djline.log.jul=true\", \"jvmInfo\" : \"mixed mode\", " +
-                "\"lastUpdated\" : { \"$numberLong\" : \"333\" }, \"jvmVersion\" : \"25.131-b12\", " +
-                "\"environment\" : [{ \"key\" : \"PATH\", \"value\" : \"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin\" }, " +
-                "{ \"key\" : \"XAUTHORITY\", \"value\" : \"/run/user/1000/gdm/Xauthority\" }, " +
-                "{ \"key\" : \"GDMSESSION\", \"value\" : \"i3\" }, { \"key\" : \"fish_greeting\", \"value\" : \"\" }, " +
-                "{ \"key\" : \"TERM\", \"value\" : \"xterm-256color\" }, { \"key\" : \"DARWIN_MODE\", \"value\" : \"0\" }, " +
-                "{ \"key\" : \"LANG\", \"value\" : \"en_US.UTF-8\" }, " +
-                "{ \"key\" : \"DBUS_SESSION_BUS_ADDRESS\", \"value\" : \"unix:path=/run/user/1000/bus\" }, " +
-                "{ \"key\" : \"XDG_SESSION_ID\", \"value\" : \"2\" }, { \"key\" : \"XDG_SESSION_TYPE\", \"value\" : \"x11\" }, " +
-                "{ \"key\" : \"XDG_CURRENT_DESKTOP\", \"value\" : \"i3\" }, { \"key\" : \"DISPLAY\", \"value\" : \":0\" }, " +
-                "{ \"key\" : \"CYGWIN_MODE\", \"value\" : \"0\" }, { \"key\" : \"COLORTERM\", \"value\" : \"truecolor\" }, " +
-                "{ \"key\" : \"_\", \"value\" : \"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java\" }], " +
-                "\"uid\" : 1000, \"username\" : \"user\", \"systemId\" : \"1\", \"isAlive\" : false }]}]}";
-
+        ContentWrapper expectedContentWrapper = new ContentWrapper().addToResponse(
+                Map.of("jvms",
+                        Array.of(
+                                Map.of("jvmName", "vm",
+                                        "lastUpdated", Map.of("$numberLong", "333"),
+                                        "vmArguments", "-Djline.log.jul=true",
+                                        "mainClass", "mc",
+                                        "javaVersion", "1.8.0_131",
+                                        "stopTime", Map.of("$numberLong", "1495727607482"),
+                                        "jvmVersion", "25.131-b12",
+                                        "jvmId", "jid2",
+                                        "username", "user",
+                                        "isAlive", false,
+                                        "jvmPid", 2,
+                                        "javaCommandLine", "j cl",
+                                        "jvmInfo", "mixed mode",
+                                        "javaHome", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre",
+                                        "startTime", Map.of("$numberLong", "1495727607481"),
+                                        "environment", Array.of(
+                                                Map.of("key", "PATH",
+                                                        "value", "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin"),
+                                                Map.of("key", "XAUTHORITY",
+                                                        "value", "/run/user/1000/gdm/Xauthority"),
+                                                Map.of("key", "GDMSESSION",
+                                                        "value", "i3"),
+                                                Map.of("key", "fish_greeting",
+                                                        "value", ""),
+                                                Map.of("key", "TERM",
+                                                        "value", "xterm-256color"),
+                                                Map.of("key", "DARWIN_MODE",
+                                                        "value", "0"),
+                                                Map.of("key", "LANG",
+                                                        "value", "en_US.UTF-8"),
+                                                Map.of("key", "DBUS_SESSION_BUS_ADDRESS",
+                                                        "value", "unix:path=/run/user/1000/bus"),
+                                                Map.of("key", "XDG_SESSION_ID",
+                                                        "value", "2"),
+                                                Map.of("key", "XDG_SESSION_TYPE",
+                                                        "value", "x11"),
+                                                Map.of("key", "XDG_CURRENT_DESKTOP",
+                                                        "value", "i3"),
+                                                Map.of("key", "DISPLAY",
+                                                        "value", ":0"),
+                                                Map.of("key", "CYGWIN_MODE",
+                                                        "value", "0"),
+                                                Map.of("key", "COLORTERM",
+                                                        "value", "truecolor"),
+                                                Map.of("key", "_",
+                                                        "value", "/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-1.b12.fc24.x86_64/jre/../bin/java")),
+                                        "uid", 1000,
+                                        "agentId", "aid",
+                                        "systemId", "1")),
+                        "systemId", "1")
+        );
 
         final String url1 = baseUrl + "/jvms/0.0/tree";
         ContentResponse response = client.newRequest(url1 + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        assertEquals(expected, response.getContentAsString());
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
 
         final String url2 = baseUrl + "/jvms/0.0.0/tree";
         response = client.newRequest(url2 + query).method(HttpMethod.GET).send();
         assertEquals(200, response.getStatus());
-        assertEquals(expected, response.getContentAsString());
+        expectedContentWrapper.matchJsonOrThrow(response.getContentAsString());
 
         final String url3 = baseUrl + "/jvms/0.0.5/tree";
         response = client.newRequest(url3 + query).method(HttpMethod.GET).send();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/tests/util/ContentWrapperTest.java	Fri Sep 01 13:08:57 2017 -0400
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.tests.util;
+
+import static com.redhat.thermostat.gateway.tests.utils.ContentWrapper.Array;
+import static com.redhat.thermostat.gateway.tests.utils.ContentWrapper.Map;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+import com.redhat.thermostat.gateway.tests.utils.ContentWrapper;
+import com.redhat.thermostat.gateway.tests.utils.HttpTestUtil;
+import org.junit.Test;
+
+public class ContentWrapperTest {
+
+    @Test
+    public void testEmptyResponseBuilder() {
+        assertEquals("{\"response\":[]}", HttpTestUtil.EMPTY_RESPONSE);
+    }
+
+    @Test
+    public void testResponseBuilderData() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToResponse(1, 3, "hi", Map.of("a", "b"));
+        assertEquals("[1,3,\"hi\",{\"a\":\"b\"}]", contentWrapper.getJsonResponseArray());
+    }
+
+    @Test
+    public void testSimpleResponseBuilder() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToResponse(
+                Map.of("answer", 42,
+                       "a", "b"),
+                Array.of(1, 2, 3)
+        );
+
+        assertThat(contentWrapper.toJson(), anyOf(
+                equalTo("{\"response\":[{\"answer\":42,\"a\":\"b\"},[1,2,3]]}"),
+                equalTo("{\"response\":[{\"a\":\"b\",\"answer\":42},[1,2,3]]}")));
+
+        String expectedResponse = "{\"response\":[{\"a\":\"b\",\"answer\":42},[1,2,3]]}";
+        contentWrapper.matchJsonOrThrow(expectedResponse);
+    }
+
+    @Test
+    public void testShouldMatchItself() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToResponse(Map.of("answer", 42), Array.of(1, 2, "hello"), "yes");
+        contentWrapper.matchJsonOrThrow(contentWrapper.toJson());
+    }
+
+    @Test
+    public void testMapOrderDoesNotMatter() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToResponse(Map.of("a", 1, "b", 2));
+        String permutationOne = "{\"response\":[{\"a\":1,\"b\":2}]}";
+        String permutationTwo = "{\"response\":[{\"b\":2,\"a\":1}]}";
+        contentWrapper.matchJsonOrThrow(permutationOne);
+        contentWrapper.matchJsonOrThrow(permutationTwo);
+    }
+
+    @Test
+    public void testLargeAmountOfObjects() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToResponse(
+                Map.of("answer", 42,
+                       "key", Map.of("something", new TestPOJO(0, -12345678, "hi"),
+                                     1, new LinkedList<TestPOJO>())),
+                Array.of(1,
+                         Array.of('a', 'b', "c"),
+                         "hello",
+                         Array.of()),
+                new TestPOJO(42, -2, "hi"),
+                1,
+                new ArrayList<Integer>(),
+                ""
+        );
+
+        String expected = "{\"response\":[{" +
+                              "\"answer\":42," +
+                              "\"key\":{" +
+                                  "\"1\":[]," +
+                                  "\"something\":{" +
+                                      "\"first\":0," +
+                                      "\"second\":-12345678," +
+                                      "\"third\":\"hi\"}" +
+                                  "}" +
+                              "}," +
+                              "[1,[\"a\",\"b\",\"c\"],\"hello\",[]]," +
+                              "{" +
+                                  "\"first\":42," +
+                                  "\"second\":-2," +
+                                  "\"third\":\"hi\"}," +
+                              "1," +
+                              "[]," +
+                              "\"\"" +
+                          "]}";
+
+        assertEquals(expected, contentWrapper.toJson());
+    }
+
+    @Test
+    public void testCanAddNewElementsToTheBuilder() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToResponse(Map.of("answer", 42));
+        assertEquals("{\"response\":[{\"answer\":42}]}", contentWrapper.toJson());
+
+        contentWrapper.addToResponse(Array.of("yes", 0));
+        assertEquals("{\"response\":[{\"answer\":42},[\"yes\",0]]}", contentWrapper.toJson());
+    }
+
+    @Test
+    public void testAddingMetadata() {
+        ContentWrapper contentWrapper = new ContentWrapper().addToMetadata("answer", 42, 1, 2);
+        assertThat(contentWrapper.toJson(), anyOf(
+                equalTo("{\"response\":[],\"metaData\":{\"answer\":42,\"1\":2}}"),
+                equalTo("{\"response\":[],\"metaData\":{\"1\":2,\"answer\":42}}")));
+    }
+
+    @Test
+    public void testAddingBothResponseAndMetadata() {
+        ContentWrapper contentWrapper = new ContentWrapper()
+                .addToResponse("a", 1)
+                .addToMetadata("answer", 42, "array", Array.of(1, 2, 3));
+        assertThat(contentWrapper.toJson(), anyOf(
+                equalTo("{\"response\":[\"a\",1],\"metaData\":{\"answer\":42,\"array\":[1,2,3]}}"),
+                equalTo("{\"response\":[\"a\",1],\"metaData\":{\"array\":[1,2,3],\"answer\":42}}")));
+
+    }
+
+    // Used to make sure objects are converted properly.
+    private class TestPOJO {
+        private int first;
+        private int second;
+        private String third;
+
+        private TestPOJO(int first, int second, String third) {
+            this.first = first;
+            this.second = second;
+            this.third = third;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/tests/util/ResponseSetWrapperTest.java	Fri Sep 01 13:08:57 2017 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.tests.util;
+
+import static org.junit.Assert.assertEquals;
+
+import com.redhat.thermostat.gateway.tests.utils.ResponseSetWrapper;
+import org.junit.Test;
+
+public class ResponseSetWrapperTest {
+
+    @Test
+    public void testSingleKey() {
+        ResponseSetWrapper setWrapper = new ResponseSetWrapper().key("k").value(1);
+        assertEquals("{\"set\":{\"k\":1}}", setWrapper.toSetString());
+
+        setWrapper = new ResponseSetWrapper().key("k").value("v");
+        assertEquals("{\"set\":{\"k\":\"v\"}}", setWrapper.toSetString());
+
+        setWrapper = new ResponseSetWrapper().key("k").valueNoQuotes("v");
+        assertEquals("{\"set\":{\"k\":v}}", setWrapper.toSetString());
+    }
+
+    @Test
+    public void testMultiKey() {
+        ResponseSetWrapper setWrapper = new ResponseSetWrapper()
+                .key("k1")
+                .key("k2")
+                .index(42)
+                .key("042")
+                .key("k3")
+                .value("value");
+        assertEquals("{\"set\":{\"k1.k2.42.042.k3\":\"value\"}}", setWrapper.toSetString());
+    }
+
+    @Test
+    public void testNestedObject() {
+        ResponseSetWrapper setWrapper = new ResponseSetWrapper()
+                .key("hi")
+                .valueNoQuotes("{\"a\":1}");
+        assertEquals("{\"set\":{\"hi\":{\"a\":1}}}", setWrapper.toSetString());
+    }
+
+    @Test
+    public void testMultipleOfTheSameKeyAllowed() {
+        ResponseSetWrapper setWrapper = new ResponseSetWrapper()
+                .key("k").value(1)
+                .key("k").value(2);
+        assertEquals("{\"set\":{\"k\":1,\"k\":2}}", setWrapper.toSetString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/ContentWrapper.java	Fri Sep 01 13:08:57 2017 -0400
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.tests.utils;
+
+import static junit.framework.TestCase.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+/**
+ * A wrapper for content that the server responds with. The primary use of this
+ * class is to be able to easily construct a response/metadata object, and to
+ * be able to compare json strings with one another regardless of map ordering.
+ * This means content like {"response":[{a: b, c: d}]} will be considered a
+ * match to {"response":[{c: d, a: b}]}.
+ */
+public class ContentWrapper {
+
+    private static final Gson gson = new Gson();
+
+    private LinkedHashMap<String, Object> elements = new LinkedHashMap<>();
+
+    /**
+     * Creates an empty content wrapper with only an empty response array
+     * present.
+     */
+    public ContentWrapper() {
+        elements.put("response", new ArrayList<JsonElement>());
+    }
+
+    /**
+     * Adds a list of objects in the order provided to the response array.
+     * Order of the elements matters since these are inserted into the array.
+     * You do not need to provide the wrapping array yourself.
+     * @param objects The elements to add to the response array list.
+     * @return The current object.
+     */
+    @SuppressWarnings("unchecked")
+    public ContentWrapper addToResponse(Object ...objects) {
+        ArrayList<JsonElement> response = (ArrayList<JsonElement>) elements.get("response");
+        response.addAll(gson.fromJson("{\"elementList\":" + gson.toJson(objects) + "}", JsonElementList.class).elementList);
+        return this;
+    }
+
+    /**
+     * Adds the objects to the metadata internal map. You do not need to pass
+     * in a Map as it will do the wrapping for you. If you want to have a map
+     * like {metadata:{a: b}} then you would just call addToMetadata("a", "b").
+     * @param objects The objects to add to the metadata map.
+     * @return The current object.
+     */
+    @SuppressWarnings("unchecked")
+    public ContentWrapper addToMetadata(Object ...objects) {
+        if (!elements.containsKey("metaData")) {
+            elements.put("metaData", new HashMap<String, JsonElement>());
+        }
+        HashMap<String, JsonElement> metaData = (HashMap<String, JsonElement>) elements.get("metaData");
+        HashMap map = Map.of(objects);
+        metaData.putAll(gson.fromJson("{\"elementMap\":" + gson.toJson(map) + "}", JsonElementMap.class).elementMap);
+        return this;
+    }
+
+    /**
+     * Checks if a string response matches the elements in this object. This
+     * makes sure they match even if the mapping order is not the same. Thus,
+     * the following would return true if our response builder contained the
+     * following:
+     *      [{"a": "b", "c": "d"}]
+     * and it was tested with:
+     *      "{\"response\":[{\"a\":\"b\",\"c\":\"d\"}]}
+     * or
+     *      "{\"response\":[{\"c\":\"d\",\"a\":\"b\"}]}
+     * Note that array ordering is required, so {response:[[1,2]]} is not the
+     * same as {response:[[2,1]]}. This goes for any nested array in the
+     * response to be checked.
+     * @param jsonString The string to check.
+     * @throws AssertionError If the match fails. This is the same as what you
+     * get when JUnit throws.
+     */
+    public void matchJsonOrThrow(String jsonString) {
+        ContentWrapper other = gson.fromJson("{\"elements\":" + jsonString + "}", ContentWrapper.class);
+        String thisString = gson.toJson(this);
+        String otherString = gson.toJson(other);
+
+        JsonParser parser = new JsonParser();
+        JsonElement expectedElements = parser.parse(thisString);
+        JsonElement actualElements = parser.parse(otherString);
+        assertEquals(expectedElements, actualElements);
+    }
+
+    /**
+     * Gets the element in Json form. The "response" field is always returned
+     * even if it's empty, but other ones (ex: metadata) will not be added to
+     * the list if there are no elements.
+     * @return A string in the json format.
+     */
+    public String toJson() {
+        return gson.toJson(elements);
+    }
+
+    /**
+     * Returns the array for the "response" element in this wrapper.
+     * @return A json-like string of the data, for example: {"response":[1,"hi"]}
+     * would return [1,"hi"].
+     * @throws IllegalStateException If there is no loaded data for the response
+     * in this element.
+     */
+    public String getJsonResponseArray() {
+        return gson.toJson(elements.get("response"));
+    }
+
+    // The following two classes mimic what Java 9 would have added, but with a
+    // slight twist on what Map.of() does by accepting a variable args amount.
+    public static class Array {
+        public static List<Object> of(Object ...values) {
+            return Arrays.asList(values);
+        }
+    }
+
+    public static class Map {
+        public static HashMap of(Object ...values) {
+            HashMap<Object, Object> map = new HashMap<>();
+            if (values != null) {
+                if (values.length % 2 != 0) {
+                    throw new IllegalStateException("Got odd number of elements, a key has no value");
+                }
+                for (int i = 0; i < values.length; i += 2) {
+                    map.put(values[i], values[i + 1]);
+                }
+            }
+            return map;
+        }
+    }
+
+    // A small class designed to get Gson to write a list as a list of
+    // 'JsonElement's so we can do recursive comparisons easily.
+    private class JsonElementList {
+        private List<JsonElement> elementList;
+    }
+
+    private class JsonElementMap {
+        private java.util.Map<String, JsonElement> elementMap;
+    }
+}
--- a/tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/HttpTestUtil.java	Mon Sep 04 09:09:12 2017 +0200
+++ b/tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/HttpTestUtil.java	Fri Sep 01 13:08:57 2017 -0400
@@ -38,14 +38,14 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.util.StringContentProvider;
 import org.eclipse.jetty.http.HttpMethod;
 
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
 public class HttpTestUtil {
 
     public static final String EMPTY_RESPONSE = "{\"response\":[]}";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-utils/src/main/java/com/redhat/thermostat/gateway/tests/utils/ResponseSetWrapper.java	Fri Sep 01 13:08:57 2017 -0400
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.tests.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A helper class for building a response set. It is designed to do method
+ * chaining with the set results. For example, if you want to set two of the
+ * following:
+ * 1) myKey.0.obj: "setFirstElement"
+ * 2) myStr: "hi"
+ *
+ * Then you can do it as follows:
+ *     <tt>new ResponseSetWrapper()</tt>
+ *     <tt>.key("myKey").index(0).key("obj").value("setFirstElement")</tt>
+ *     <tt>.key("myStr").value("hi")</tt>
+ *
+ * You can then get the string with <tt>.toSetString()</tt>. This would
+ * return:
+ * <tt>{"set":{"myKey.0.obj":"setFirstElement","myStr":"hi"}}</tt>
+ *
+ * If you want to nest an object or do something without quotes, then
+ * <tt>valueNoQuotes()</tt> will do that.
+ *
+ * Finally, it should be noted that <tt>.key("1")</tt> and <tt>.index(1)</tt>
+ * do the same thing, but it just indicates more clearly that you're aiming to
+ * get an index from some array.
+ *
+ * Note that getting the string does not unset the internal state, so it's
+ * possible to get the string and then continue adding more keys.
+ *
+ * The intent is that after each 'value' call, a key/value pair is deployed as
+ * an element that will be written in the final <tt>.toSetString()</tt> call.
+ *
+ * As a final note: Multiple keys can be entered, so you can do something like:
+ *     <tt>wrapper.key("a").value(1).key("a").value(2)</tt>
+ * the result will be {"set": {"a": 1, "a", 2}} which we must support since
+ * there are unit test cases that require duplicates.
+ */
+public class ResponseSetWrapper {
+
+    private List<String> keyValues = new ArrayList<>();
+    private String currentKey = "";
+
+    private void prefixKeyWithAppropriateCharacter() {
+        if (currentKey.isEmpty()) {
+            // Since keys are always quoted strings, they must begin with quotes.
+            currentKey += "\"";
+        } else {
+            currentKey += ".";
+        }
+    }
+
+    public ResponseSetWrapper key(String key) {
+        prefixKeyWithAppropriateCharacter();
+        currentKey += key;
+        return this;
+    }
+
+    public ResponseSetWrapper index(int index) {
+        prefixKeyWithAppropriateCharacter();
+        currentKey += index;
+        return this;
+    }
+
+    public ResponseSetWrapper value(String str) {
+        return value(str, true);
+    }
+
+    public ResponseSetWrapper valueNoQuotes(String str) {
+        return value(str, false);
+    }
+
+    public ResponseSetWrapper value(int i) {
+        return value(Integer.toString(i), false);
+    }
+
+    private ResponseSetWrapper value(String str, boolean addQuotes) {
+        if (currentKey.isEmpty()) {
+            throw new IllegalStateException("Cannot finish a value with no key being set");
+        }
+        keyValues.add(String.format(addQuotes ? "%s\":\"%s\"" : "%s\":%s", currentKey, str));
+        currentKey = "";
+        return this;
+    }
+
+    public String toSetString() {
+        if (keyValues.isEmpty()) {
+            return "{\"set\":{}}";
+        }
+
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("{\"set\":{");
+        for (int i = 0; i < keyValues.size() - 1; i++) {
+            stringBuilder.append(keyValues.get(i));
+            stringBuilder.append(",");
+        }
+        stringBuilder.append(keyValues.get(keyValues.size() - 1));
+        stringBuilder.append("}}");
+        return stringBuilder.toString();
+    }
+}