diff --git a/projects/cadcAccessControl/build.xml b/projects/cadcAccessControl/build.xml
index 82f0e2c62be27a1548a145a699f0695183afbcd7..4eab166665173e7055d0335620c699ddf90e1ffc 100644
--- a/projects/cadcAccessControl/build.xml
+++ b/projects/cadcAccessControl/build.xml
@@ -125,7 +125,7 @@
                 <pathelement path="${build}/test/class"/>
                 <pathelement path="${testingJars}"/>
             </classpath>
-            <test name="ca.nrc.cadc.ac.json.GroupReaderWriterTest" />
+            <test name="ca.nrc.cadc.ac.json.JsonGroupReaderWriterTest" />
             <formatter type="plain" usefile="false" />
         </junit>
     </target>
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java
index 9d8055828d911f509543906fd9106ba9f92d706e..a240184be0794193897d8924ce1002747b5ecb4c 100755
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java
@@ -68,26 +68,20 @@
  */
 package ca.nrc.cadc.ac.json;
 
-import ca.nrc.cadc.ac.AC;
 import ca.nrc.cadc.ac.Group;
 import ca.nrc.cadc.ac.ReaderException;
-import ca.nrc.cadc.ac.User;
-import ca.nrc.cadc.date.DateUtil;
-import org.json.JSONArray;
+import ca.nrc.cadc.ac.xml.GroupReader;
+import ca.nrc.cadc.xml.JsonInputter;
+import org.jdom2.Document;
 import org.json.JSONException;
-import org.json.JSONObject;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.net.URISyntaxException;
-import java.security.Principal;
-import java.text.DateFormat;
-import java.text.ParseException;
 import java.util.Scanner;
 
-public class JsonGroupReader
+public class JsonGroupReader extends GroupReader
 {
     /**
      * Construct a Group from a InputStream.
@@ -96,9 +90,9 @@ public class JsonGroupReader
      * @return Group Group.
      * @throws ReaderException
      * @throws IOException
-     * @throws URISyntaxException
      */
-    public static Group read(InputStream in)
+    @Override
+    public Group read(InputStream in)
         throws ReaderException, IOException
     {
         if (in == null)
@@ -120,9 +114,9 @@ public class JsonGroupReader
      * @return Group Group.
      * @throws ReaderException
      * @throws IOException
-     * @throws URISyntaxException
      */
-    public static Group read(Reader reader)
+    @Override
+    public Group read(Reader reader)
         throws ReaderException, IOException
     {
         if (reader == null)
@@ -143,9 +137,9 @@ public class JsonGroupReader
      * @return Group Group.
      * @throws ReaderException
      * @throws IOException
-     * @throws URISyntaxException
      */
-    public static Group read(String json)
+    @Override
+    public Group read(String json)
         throws ReaderException, IOException
     {
         if (json == null)
@@ -156,7 +150,17 @@ public class JsonGroupReader
         // Create a JSONObject from the JSON
         try
         {
-            return parseGroup(new JSONObject(json).getJSONObject("group"));
+            JsonInputter jsonInputter = new JsonInputter();
+            jsonInputter.getListElementMap().put("identities", "identity");
+            jsonInputter.getListElementMap().put("properties", "property");
+            jsonInputter.getListElementMap().put("details", "userDetails");
+            jsonInputter.getListElementMap().put("groupMembers", "group");
+            jsonInputter.getListElementMap().put("groupAdmins", "group");
+            jsonInputter.getListElementMap().put("userMembers", "user");
+            jsonInputter.getListElementMap().put("userAdmins", "user");
+
+            Document document = jsonInputter.input(json);
+            return GroupReader.parseGroup(document.getRootElement());
         }
         catch (JSONException e)
         {
@@ -166,113 +170,4 @@ public class JsonGroupReader
         }
     }
 
-    protected static Group parseGroup(JSONObject groupObject)
-        throws ReaderException, JSONException
-    {
-        String uri = groupObject.getString("uri");
-
-        // Group groupID
-        int index = uri.indexOf(AC.GROUP_URI);
-        if (index == -1)
-        {
-            String error = "group uri attribute malformed: " + uri;
-            throw new ReaderException(error);
-        }
-        String groupID = uri.substring(AC.GROUP_URI.length());
-
-        // Group owner
-        User<? extends Principal> user = null;
-        if (groupObject.has("owner"))
-        {
-            JSONObject ownerObject = groupObject.getJSONObject("owner");
-            JSONObject userObject = ownerObject.getJSONObject("user");
-            user = JsonUserReader.parseUser(userObject);
-        }
-
-        Group group = new Group(groupID, user);
-
-        // description
-        if (groupObject.has("description"))
-        {
-            group.description = groupObject.getString("description");
-        }
-
-        // lastModified
-        if (groupObject.has("lastModified"))
-        {
-            try
-            {
-                DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC);
-                group.lastModified = df.parse(groupObject.getString("lastModified"));
-            }
-            catch (ParseException e)
-            {
-                String error = "Unable to parse group lastModified because " + e.getMessage();
-
-                throw new ReaderException(error);
-            }
-        }
-
-        // properties
-        if (groupObject.has("description"))
-        {
-            JSONArray propertiesArray = groupObject.getJSONArray("properties");
-            for (int i = 0; i < propertiesArray.length(); i++)
-            {
-                JSONObject propertiesObject = propertiesArray.getJSONObject(i);
-                JSONObject propertyObject = propertiesObject.getJSONObject("property");
-                group.getProperties().add(JsonGroupPropertyReader.read(propertyObject));
-            }
-        }
-
-        // groupMembers
-        if (groupObject.has("groupMembers"))
-        {
-            JSONArray groupMembersArray = groupObject.getJSONArray("groupMembers");
-            for (int i = 0; i < groupMembersArray.length(); i++)
-            {
-                JSONObject groupMembersObject = groupMembersArray.getJSONObject(i);
-                JSONObject groupMemberObject = groupMembersObject.getJSONObject("group");
-                group.getGroupMembers().add(parseGroup(groupMemberObject));
-            }
-        }
-
-        // userMembers
-        if (groupObject.has("userMembers"))
-        {
-            JSONArray userMembersArray = groupObject.getJSONArray("userMembers");
-            for (int i = 0; i < userMembersArray.length(); i++)
-            {
-                JSONObject userMemberObject = userMembersArray.getJSONObject(i);
-                JSONObject userObject = userMemberObject.getJSONObject("user");
-                group.getUserMembers().add(JsonUserReader.parseUser(userObject));
-            }
-        }
-
-        // groupAdmins
-        if (groupObject.has("groupAdmins"))
-        {
-            JSONArray groupAdminsArray = groupObject.getJSONArray("groupAdmins");
-            for (int i = 0; i < groupAdminsArray.length(); i++)
-            {
-                JSONObject groupAdminsObject = groupAdminsArray.getJSONObject(i);
-                JSONObject groupAdminObject = groupAdminsObject.getJSONObject("group");
-                group.getGroupAdmins().add(parseGroup(groupAdminObject));
-            }
-        }
-
-        // userAdmins
-        if (groupObject.has("userAdmins"))
-        {
-            JSONArray userAdminsArray = groupObject.getJSONArray("userAdmins");
-            for (int i = 0; i < userAdminsArray.length(); i++)
-            {
-                JSONObject userAdminObject = userAdminsArray.getJSONObject(i);
-                JSONObject userObject = userAdminObject.getJSONObject("user");
-                group.getUserAdmins().add(JsonUserReader.parseUser(userObject));
-            }
-        }
-
-        return group;
-    }
 }
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java
index aa78fa68a379ac903cc63fe005bd66d3fecdf699..2db229327ce52306744846b95f0a4ffb19f310ce 100755
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java
@@ -68,16 +68,13 @@
  */
 package ca.nrc.cadc.ac.json;
 
-import ca.nrc.cadc.ac.AC;
 import ca.nrc.cadc.ac.Group;
-import ca.nrc.cadc.ac.GroupProperty;
-import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.WriterException;
-import ca.nrc.cadc.date.DateUtil;
+import ca.nrc.cadc.ac.xml.GroupWriter;
 import ca.nrc.cadc.util.StringBuilderWriter;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import ca.nrc.cadc.xml.JsonOutputter;
+import org.jdom2.Document;
+import org.jdom2.Element;
 
 import java.io.BufferedWriter;
 import java.io.IOException;
@@ -85,10 +82,8 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
-import java.security.Principal;
-import java.text.DateFormat;
 
-public class JsonGroupWriter
+public class JsonGroupWriter extends GroupWriter
 {
     /**
      * Write a Group to a StringBuilder.
@@ -97,7 +92,7 @@ public class JsonGroupWriter
      * @throws IOException
      * @throws WriterException
      */
-    public static void write(Group group, StringBuilder builder)
+    public void write(Group group, StringBuilder builder)
         throws IOException, WriterException
     {
         write(group, new StringBuilderWriter(builder));
@@ -111,7 +106,8 @@ public class JsonGroupWriter
      * @throws IOException if the writer fails to write.
      * @throws WriterException
      */
-    public static void write(Group group, OutputStream out)
+    @Override
+    public void write(Group group, OutputStream out)
         throws IOException, WriterException
     {
         OutputStreamWriter outWriter;
@@ -134,7 +130,8 @@ public class JsonGroupWriter
      * @throws IOException if the writer fails to write.
      * @throws WriterException
      */
-    public static void write(Group group, Writer writer)
+    @Override
+    public void write(Group group, Writer writer)
         throws IOException, WriterException
     {
         if (group == null)
@@ -142,116 +139,22 @@ public class JsonGroupWriter
             throw new WriterException("null group");
         }
 
-        try
-        {
-            getGroupObject(group).write(writer);
-        }
-        catch (JSONException e)
-        {
-            final String error = "Unable to create JSON for Group " +
-                                 " because " + e.getMessage();
-            throw new WriterException(error, e);
-        }
-    }
-
-    /**
-     *
-     * @param group
-     * @return
-     * @throws WriterException
-     */
-    public static JSONObject getGroupObject(Group group)
-        throws WriterException, JSONException
-    {
-        return getGroupObject(group, true);
-    }
-
-    public static JSONObject getGroupObject(Group group, boolean deepCopy)
-        throws WriterException, JSONException
-    {
-        JSONObject groupObject = new JSONObject();
-        groupObject.put("uri", AC.GROUP_URI + group.getID());
-
-        // Group owner
-        if (group.getOwner() != null)
-        {
-            groupObject.put("owner", JsonUserWriter.getUserObject(group.getOwner()));
-        }
-
-        if (deepCopy)
-        {
-            // Group description
-            if (group.description != null)
-            {
-                groupObject.put("description", group.description);
-            }
-
-            // lastModified
-            if (group.lastModified != null)
-            {
-                DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC);
-                groupObject.put("lastModified", df.format(group.lastModified));
-            }
-
-            // Group properties
-            if (!group.getProperties().isEmpty())
-            {
-                JSONArray propertiesArray = new JSONArray();
-                for (GroupProperty property : group.getProperties())
-                {
-                    JSONObject propertyObject = new JSONObject();
-                    propertyObject.put("property", JsonGroupPropertyWriter.write(property));
-                    propertiesArray.put(propertyObject);
-                }
-                groupObject.put("properties", propertiesArray);
-            }
-
-            // Group groupMembers.
-            if ((group.getGroupMembers() != null) && (!group.getGroupMembers().isEmpty()))
-            {
-                JSONArray groupMembersArray = new JSONArray();
-                for (Group groupMember : group.getGroupMembers())
-                {
-                    groupMembersArray.put(getGroupObject(groupMember, false));
-                }
-                groupObject.put("groupMembers", groupMembersArray);
-            }
-
-            // Group userMembers
-            if ((group.getUserMembers() != null) && (!group.getUserMembers().isEmpty()))
-            {
-                JSONArray userMembersArray = new JSONArray();
-                for (User<? extends Principal> userMember : group.getUserMembers())
-                {
-                    userMembersArray.put(JsonUserWriter.getUserObject(userMember));
-                }
-                groupObject.put("userMembers", userMembersArray);
-            }
-
-            // Group groupAdmins.
-            if ((group.getGroupAdmins() != null) && (!group.getGroupAdmins().isEmpty()))
-            {
-                JSONArray groupAdminsArray = new JSONArray();
-                for (Group groupAdmin : group.getGroupAdmins())
-                {
-                    groupAdminsArray.put(getGroupObject(groupAdmin, false));
-                }
-                groupObject.put("groupAdmins", groupAdminsArray);
-            }
-
-            // Group userAdmins
-            if ((group.getUserAdmins() != null) && (!group.getUserAdmins().isEmpty()))
-            {
-                JSONArray userAdminsArray = new JSONArray();
-                for (User<? extends Principal> userAdmin : group.getUserAdmins())
-                {
-                    userAdminsArray.put(JsonUserWriter.getUserObject(userAdmin));
-                }
-                groupObject.put("userAdmins", userAdminsArray);
-            }
-        }
-
-        return new JSONObject().put("group", groupObject);
+        Element children = GroupWriter.getGroupElement(group);
+        Element groupElement = new Element("group");
+        groupElement.addContent(children);
+        Document document = new Document();
+        document.setRootElement(groupElement);
+
+        JsonOutputter jsonOutputter = new JsonOutputter();
+        jsonOutputter.getListElementNames().add("properties");
+        jsonOutputter.getListElementNames().add("userMembers");
+        jsonOutputter.getListElementNames().add("groupMembers");
+        jsonOutputter.getListElementNames().add("userAdmins");
+        jsonOutputter.getListElementNames().add("groupAdmins");
+        jsonOutputter.getListElementNames().add("identities");
+        jsonOutputter.getListElementNames().add("details");
+
+        jsonOutputter.output(document, writer);
     }
 
 }
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java
index f2d9db38d3c5459c8d86b0cf2f7c9d9f870d5230..2c4a8e376ec338c5fa2157d08767ca79f8999d5d 100755
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java
@@ -70,10 +70,10 @@ package ca.nrc.cadc.ac.json;
 
 import ca.nrc.cadc.ac.ReaderException;
 import ca.nrc.cadc.ac.User;
-import ca.nrc.cadc.ac.UserDetails;
-import org.json.JSONArray;
+import ca.nrc.cadc.ac.xml.UserReader;
+import ca.nrc.cadc.xml.JsonInputter;
+import org.jdom2.Document;
 import org.json.JSONException;
-import org.json.JSONObject;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -81,7 +81,7 @@ import java.io.Reader;
 import java.security.Principal;
 import java.util.Scanner;
 
-public class JsonUserReader
+public class JsonUserReader extends UserReader
 {
     /**
      * Construct a User from a InputStream.
@@ -91,7 +91,8 @@ public class JsonUserReader
      * @throws ReaderException
      * @throws IOException
      */
-    public static User<Principal> read(InputStream in)
+    @Override
+    public User<Principal> read(InputStream in)
         throws IOException
     {
         if (in == null)
@@ -113,7 +114,8 @@ public class JsonUserReader
      * @throws ReaderException
      * @throws IOException
      */
-    public static User<Principal> read(Reader reader)
+    @Override
+    public User<Principal> read(Reader reader)
         throws IOException
     {
         if (reader == null)
@@ -135,7 +137,8 @@ public class JsonUserReader
      * @throws ReaderException
      * @throws IOException
      */
-    public static User<Principal> read(String json)
+    @Override
+    public User<Principal> read(String json)
         throws IOException
     {
         if (json == null || json.isEmpty())
@@ -146,50 +149,19 @@ public class JsonUserReader
         // Create a JSONObject from the JSON
         try
         {
-            return parseUser(new JSONObject(json).getJSONObject("user"));
+            JsonInputter jsonInputter = new JsonInputter();
+            jsonInputter.getListElementMap().put("identities", "identity");
+            jsonInputter.getListElementMap().put("details", "userDetails");
+
+            Document document = jsonInputter.input(json);
+            return UserReader.parseUser(document.getRootElement());
         }
         catch (JSONException e)
         {
             String error = "Unable to parse JSON to User because " +
-                           e.getMessage();
+                e.getMessage();
             throw new ReaderException(error, e);
         }
     }
 
-    protected static User<Principal> parseUser(JSONObject userObject)
-        throws ReaderException, JSONException
-    {
-        JSONObject userIDObject = userObject.getJSONObject("userID");
-        JSONObject userIDIdentityObject = userIDObject.getJSONObject("identity");
-
-        Principal userID = JsonIdentityReader.read(userIDIdentityObject);
-        User<Principal> user = new User<Principal>(userID);
-
-        // identities
-        if (userObject.has("identities"))
-        {
-            JSONArray identitiesArray = userObject.getJSONArray("identities");
-            for (int i = 0; i < identitiesArray.length(); i++)
-            {
-                JSONObject identitiesObject = identitiesArray.getJSONObject(i);
-                JSONObject identityObject = identitiesObject.getJSONObject(("identity"));
-                user.getIdentities().add(JsonIdentityReader.read(identityObject));
-            }
-        }
-
-        // details
-        if (userObject.has("details"))
-        {
-            JSONArray detailsArray = userObject.getJSONArray("details");
-            for (int i = 0; i < detailsArray.length(); i++)
-            {
-                JSONObject detailsObject = detailsArray.getJSONObject(i);
-                JSONObject userDetailsObject = detailsObject.getJSONObject(UserDetails.NAME);
-                user.details.add(JsonUserDetailsReader.read(userDetailsObject));
-            }
-        }
-
-        return user;
-    }
-
 }
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java
index 2a5c8d394e39520237c503d6937a50445be0b460..b8d61e8cea9567a2caac1beb562766a5e05b1bfa 100644
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java
@@ -69,46 +69,20 @@
 package ca.nrc.cadc.ac.json;
 
 import ca.nrc.cadc.ac.ReaderException;
-import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.UserRequest;
+import ca.nrc.cadc.ac.xml.UserRequestReader;
+import ca.nrc.cadc.xml.JsonInputter;
+import org.jdom2.Document;
 import org.json.JSONException;
-import org.json.JSONObject;
 
-import java.io.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
 import java.security.Principal;
 import java.util.Scanner;
 
-public class JsonUserRequestReader
+public class JsonUserRequestReader extends UserRequestReader
 {
-    /**
-     * Construct a UserRequest from an JSON String source.
-     *
-     * @param json String of the JSON.
-     * @return UserRequest UserRequest.
-     * @throws IOException
-     */
-    public static UserRequest<Principal> read(String json)
-        throws IOException
-    {
-        if (json == null)
-        {
-            throw new IllegalArgumentException("JSON must not be null");
-        }
-        else
-        {
-            try
-            {
-                return parseUserRequest(new JSONObject(json));
-            }
-            catch (JSONException e)
-            {
-                String error = "Unable to parse JSON to User because " +
-                               e.getMessage();
-                throw new ReaderException(error, e);
-            }
-        }
-    }
-
     /**
      * Construct a User from a InputStream.
      *
@@ -117,7 +91,8 @@ public class JsonUserRequestReader
      * @throws ReaderException
      * @throws IOException
      */
-    public static UserRequest<Principal> read(InputStream in)
+    @Override
+    public UserRequest<Principal> read(InputStream in)
             throws IOException
     {
         if (in == null)
@@ -139,7 +114,8 @@ public class JsonUserRequestReader
      * @throws ReaderException
      * @throws IOException
      */
-    public static UserRequest<Principal> read(Reader reader)
+    @Override
+    public UserRequest<Principal> read(Reader reader)
             throws IOException
     {
         if (reader == null)
@@ -153,16 +129,39 @@ public class JsonUserRequestReader
         return read(json);
     }
 
-
-    protected static UserRequest<Principal> parseUserRequest(
-            JSONObject userRequestObject)
-        throws ReaderException, JSONException
+    /**
+     * Construct a UserRequest from an JSON String source.
+     *
+     * @param json String of the JSON.
+     * @return UserRequest UserRequest.
+     * @throws IOException
+     */
+    @Override
+    public UserRequest<Principal> read(String json)
+        throws IOException
     {
-        final User<Principal> user =
-                JsonUserReader.parseUser(
-                    userRequestObject.getJSONObject("user"));
+        if (json == null)
+        {
+            throw new IllegalArgumentException("JSON must not be null");
+        }
+        else
+        {
+            try
+            {
+                JsonInputter jsonInputter = new JsonInputter();
+                jsonInputter.getListElementMap().put("identities", "identity");
+                jsonInputter.getListElementMap().put("details", "userDetails");
 
-        return new UserRequest<Principal>(user, userRequestObject.
-                getString("password").toCharArray());
+                Document document = jsonInputter.input(json);
+                return UserRequestReader.parseUserRequest(document.getRootElement());
+            }
+            catch (JSONException e)
+            {
+                String error = "Unable to parse JSON to User because " +
+                    e.getMessage();
+                throw new ReaderException(error, e);
+            }
+        }
     }
+
 }
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ebb07a652a9b972252d528e869ac86938d33c12
--- /dev/null
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestWriter.java
@@ -0,0 +1,63 @@
+package ca.nrc.cadc.ac.json;
+
+import ca.nrc.cadc.ac.UserRequest;
+import ca.nrc.cadc.ac.WriterException;
+import ca.nrc.cadc.ac.xml.UserRequestWriter;
+import ca.nrc.cadc.util.StringBuilderWriter;
+import ca.nrc.cadc.xml.JsonOutputter;
+import org.jdom2.Document;
+import org.jdom2.Element;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.security.Principal;
+
+/**
+ * Class to write a JSON representation of a UserRequest object.
+ */
+public class JsonUserRequestWriter extends UserRequestWriter
+{
+    /**
+     * Write a UserRequest to a StringBuilder.
+     *
+     * @param userRequest UserRequest to write.
+     * @param builder StringBuilder to write to.
+     * @throws java.io.IOException if the writer fails to write.
+     * @throws WriterException
+     */
+    public void write(UserRequest<? extends Principal> userRequest, StringBuilder builder)
+        throws IOException, WriterException
+    {
+        write(userRequest, new StringBuilderWriter(builder));
+    }
+
+    /**
+     * Write a UserRequest to a Writer.
+     *
+     * @param userRequest UserRequest to write.
+     * @param writer Writer to write to.
+     * @throws IOException if the writer fails to write.
+     * @throws WriterException
+     */
+    public static void write(UserRequest<? extends Principal> userRequest, Writer writer)
+        throws IOException, WriterException
+    {
+        if (userRequest == null)
+        {
+            throw new WriterException("null UserRequest");
+        }
+
+        Element children = UserRequestWriter.getUserRequestElement(userRequest);
+        Element userRequestElement = new Element("userRequest");
+        userRequestElement.addContent(children);
+        Document document = new Document();
+        document.setRootElement(userRequestElement);
+
+        JsonOutputter jsonOutputter = new JsonOutputter();
+        jsonOutputter.getListElementNames().add("identities");
+        jsonOutputter.getListElementNames().add("details");
+
+        jsonOutputter.output(document, writer);
+    }
+
+}
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java
index 41da645e0ad3cac0a85bcfcde103520644bc5fd4..444a670a4453e0bd2e6b7f481fb9247e73df0525 100755
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java
@@ -71,7 +71,12 @@ package ca.nrc.cadc.ac.json;
 import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.UserDetails;
 import ca.nrc.cadc.ac.WriterException;
+import ca.nrc.cadc.ac.xml.GroupWriter;
+import ca.nrc.cadc.ac.xml.UserWriter;
 import ca.nrc.cadc.util.StringBuilderWriter;
+import ca.nrc.cadc.xml.JsonOutputter;
+import org.jdom2.Document;
+import org.jdom2.Element;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -85,7 +90,7 @@ import java.io.Writer;
 import java.security.Principal;
 import java.util.Set;
 
-public class JsonUserWriter
+public class JsonUserWriter extends UserWriter
 {
     /**
      * Write a User as a JSON string to a StringBuilder.
@@ -95,7 +100,8 @@ public class JsonUserWriter
      * @throws IOException if the writer fails to write.
      * @throws WriterException
      */
-    public static void write(User<? extends Principal> user, StringBuilder builder)
+    @Override
+    public void write(User<? extends Principal> user, StringBuilder builder)
         throws IOException, WriterException
     {
         write(user, new StringBuilderWriter(builder));
@@ -109,7 +115,8 @@ public class JsonUserWriter
      * @throws IOException if the writer fails to write.
      * @throws WriterException
      */
-    public static void write(User<? extends Principal> user, OutputStream out)
+    @Override
+    public void write(User<? extends Principal> user, OutputStream out)
         throws IOException, WriterException
     {                
         OutputStreamWriter outWriter;
@@ -132,7 +139,8 @@ public class JsonUserWriter
      * @throws IOException if the writer fails to write.
      * @throws WriterException
      */
-    public static void write(User<? extends Principal> user, Writer writer)
+    @Override
+    public void write(User<? extends Principal> user, Writer writer)
         throws IOException, WriterException
     {
         if (user == null)
@@ -140,62 +148,17 @@ public class JsonUserWriter
             throw new WriterException("null User");
         }
 
-        try
-        {
-            getUserObject(user).write(writer);
-        }
-        catch (JSONException e)
-        {
-            final String error = "Unable to create JSON for User " +
-                                 " because " + e.getMessage();
-            throw new WriterException(error, e);
-        }
-    }
+        Element children = UserWriter.getUserElement(user);
+        Element userElement = new Element("user");
+        userElement.addContent(children);
+        Document document = new Document();
+        document.setRootElement(userElement);
 
-    /**
-     * Build a User JSONObject from a User.
-     *
-     * @param user User.
-     * @return JSONObject.
-     * @throws WriterException
-     */
-    public static JSONObject getUserObject(User<? extends Principal> user)
-        throws WriterException, JSONException
-    {
-        JSONObject userObject = new JSONObject();
-        JSONObject userIDIdentityObject = new JSONObject();
-        userIDIdentityObject.put("identity", JsonIdentityWriter.write(user.getUserID()));
-        userObject.put("userID", userIDIdentityObject);
-
-        // identities
-        Set<Principal> identities = user.getIdentities();
-        if (!identities.isEmpty())
-        {
-            JSONArray identityArray = new JSONArray();
-            for (Principal identity : identities)
-            {
-                JSONObject identityObject = new JSONObject();
-                identityObject.put("identity" , JsonIdentityWriter.write(identity));
-                identityArray.put(identityObject);
-            }
-            userObject.put("identities", identityArray);
-        }
-
-        // details
-        if (!user.details.isEmpty())
-        {
-            JSONArray detailsArray = new JSONArray();
-            Set<UserDetails> userDetails = user.details;
-            for (UserDetails userDetail : userDetails)
-            {
-                JSONObject detailsObject = new JSONObject();
-                detailsObject.put(UserDetails.NAME , JsonUserDetailsWriter.write(userDetail));
-                detailsArray.put(detailsObject);
-            }
-            userObject.put("details", detailsArray);
-        }
+        JsonOutputter jsonOutputter = new JsonOutputter();
+        jsonOutputter.getListElementNames().add("identities");
+        jsonOutputter.getListElementNames().add("details");
 
-        return new JSONObject().put("user", userObject);
+        jsonOutputter.output(document, writer);
     }
 
 }
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java
index 8a66c7e95aef3e98abffdb2906bb0bf369a9f4a6..0f0d1dca1233d54a01c9cbb0da2ba9685fffc18c 100755
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java
@@ -184,7 +184,7 @@ public class GroupReader
         return parseGroup(root);
     }
 
-    protected static Group parseGroup(Element groupElement)
+    public static Group parseGroup(Element groupElement)
         throws ReaderException
     {
         String uri = groupElement.getAttributeValue("uri");
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java
index 7cceba392b1852cedacbe10a1f25bd04a06492bf..0accd9da28358bd855b9b73c0d10ce8265044872 100755
--- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java
@@ -169,7 +169,7 @@ public class UserReader
         return parseUser(root);
     }
 
-    protected static User<Principal> parseUser(Element userElement)
+    public static User<Principal> parseUser(Element userElement)
         throws ReaderException
     {
         // userID element of the User element
diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java
index 970c112d64728cf4055c17255cd072aaccd79794..1de1fab5bf1cf8acc3e633644719c1204c55fb2f 100644
--- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java
+++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java
@@ -70,11 +70,16 @@ package ca.nrc.cadc.ac.json;
 
 import ca.nrc.cadc.ac.Group;
 import ca.nrc.cadc.ac.GroupProperty;
+import ca.nrc.cadc.ac.PersonalDetails;
+import ca.nrc.cadc.ac.PosixDetails;
 import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.WriterException;
 import ca.nrc.cadc.auth.HttpPrincipal;
 import ca.nrc.cadc.auth.OpenIdPrincipal;
+import ca.nrc.cadc.util.Log4jInit;
+import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import javax.security.auth.x500.X500Principal;
@@ -97,6 +102,12 @@ public class JsonGroupReaderWriterTest
 {
     private static Logger log = Logger.getLogger(JsonGroupReaderWriterTest.class);
 
+    @BeforeClass
+    public static void setUpClass()
+    {
+        Log4jInit.setLevel("ca.nrc.cadc.ac.json", Level.INFO);
+    }
+
     @Test
     public void testReaderExceptions()
         throws Exception
@@ -104,7 +115,8 @@ public class JsonGroupReaderWriterTest
         try
         {
             String s = null;
-            Group g = JsonGroupReader.read(s);
+            JsonGroupReader reader = new JsonGroupReader();
+            Group g = reader.read(s);
             fail("null String should throw IllegalArgumentException");
         }
         catch (IllegalArgumentException e) {}
@@ -112,7 +124,8 @@ public class JsonGroupReaderWriterTest
         try
         {
             InputStream in = null;
-            Group g = JsonGroupReader.read(in);
+            JsonGroupReader reader = new JsonGroupReader();
+            Group g = reader.read(in);
             fail("null InputStream should throw IOException");
         }
         catch (IOException e) {}
@@ -120,7 +133,8 @@ public class JsonGroupReaderWriterTest
         try
         {
             Reader r = null;
-            Group g = JsonGroupReader.read(r);
+            JsonGroupReader reader = new JsonGroupReader();
+            Group g = reader.read(r);
             fail("null element should throw ReaderException");
         }
         catch (IllegalArgumentException e) {}
@@ -132,7 +146,8 @@ public class JsonGroupReaderWriterTest
     {
         try
         {
-            JsonGroupWriter.write(null, new StringBuilder());
+            JsonGroupWriter writer = new JsonGroupWriter();
+            writer.write(null, new StringBuilder());
             fail("null Group should throw WriterException");
         }
         catch (WriterException e) {}
@@ -142,41 +157,63 @@ public class JsonGroupReaderWriterTest
     public void testMinimalReadWrite()
         throws Exception
     {
-        Group expected = new Group("groupID", null);
+        Group expected = new Group("groupID");
                 
         StringBuilder json = new StringBuilder();
-        JsonGroupWriter.write(expected, json);
+        JsonGroupWriter writer = new JsonGroupWriter();
+        writer.write(expected, json);
         assertFalse(json.toString().isEmpty());
-        
-        Group actual = JsonGroupReader.read(json.toString());
+
+        JsonGroupReader reader = new JsonGroupReader();
+        Group actual = reader.read(json.toString());
         assertNotNull(actual);
         assertEquals(expected, actual);
     }
-    
+
     @Test
     public void testMaximalReadWrite()
         throws Exception
     {
-        Group expected = new Group("groupID", new User<Principal>(new HttpPrincipal("foo")));
+        User<Principal> owner = new User<Principal>(new HttpPrincipal("foo"));
+        X500Principal x500Principal = new X500Principal("cn=foo,o=bar");
+        owner.getIdentities().add(x500Principal);
+        PersonalDetails personalDetails = new PersonalDetails("foo", "bar");
+        personalDetails.address = "address";
+        personalDetails.email = "email";
+        personalDetails.institute = "institute";
+        personalDetails.city = "city";
+        personalDetails.country = "country";
+        owner.details.add(personalDetails);
+        PosixDetails posixDetails = new PosixDetails(123L, 456L, "/dev/null");
+        owner.details.add(posixDetails);
+
+        Group expected = new Group("groupID", owner);
         expected.description = "description";
         expected.lastModified = new Date();
-        expected.getProperties().add(new GroupProperty("key", "value", true));
-        
+        expected.getProperties().add(new GroupProperty("key1", "value1", true));
+        expected.getProperties().add(new GroupProperty("key2", "value2", true));
+        expected.getProperties().add(new GroupProperty("key3", "value3", true));
+
         Group groupMember = new Group("member", new User<Principal>(new OpenIdPrincipal("bar")));
         User<Principal> userMember = new User<Principal>(new HttpPrincipal("baz"));
         Group groupAdmin = new Group("admin", new User<Principal>(new X500Principal("cn=foo,o=ca")));
         User<Principal> userAdmin = new User<Principal>(new HttpPrincipal("admin"));
-        
+
         expected.getGroupMembers().add(groupMember);
         expected.getUserMembers().add(userMember);
         expected.getGroupAdmins().add(groupAdmin);
         expected.getUserAdmins().add(userAdmin);
-        
-        StringBuilder json = new StringBuilder();
-        JsonGroupWriter.write(expected, json);
-        assertFalse(json.toString().isEmpty());
 
-        Group actual = JsonGroupReader.read(json.toString());
+        JsonGroupWriter writer = new JsonGroupWriter();
+        StringBuilder sb = new StringBuilder();
+        writer.write(expected, sb);
+
+        String json = sb.toString();
+        log.debug(json);
+
+        JsonGroupReader reader = new JsonGroupReader();
+        Group actual = reader.read(json);
+
         assertNotNull(actual);
         assertEquals(expected, actual);
         assertEquals(expected.description, actual.description);
diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java
index bc3a7c0fb491f9edf84341a921800ec19cd2106d..dccefe894c2a5b2a3addf25e226cee910061ea74 100644
--- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java
+++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java
@@ -102,7 +102,8 @@ public class JsonUserReaderWriterTest
         try
         {
             String s = null;
-            User<? extends Principal> u = JsonUserReader.read(s);
+            JsonUserReader reader = new JsonUserReader();
+            User<? extends Principal> u = reader.read(s);
             fail("null String should throw IllegalArgumentException");
         }
         catch (IllegalArgumentException e) {}
@@ -110,7 +111,8 @@ public class JsonUserReaderWriterTest
         try
         {
             InputStream in = null;
-            User<? extends Principal> u = JsonUserReader.read(in);
+            JsonUserReader reader = new JsonUserReader();
+            User<? extends Principal> u = reader.read(in);
             fail("null InputStream should throw IOException");
         }
         catch (IOException e) {}
@@ -118,7 +120,8 @@ public class JsonUserReaderWriterTest
         try
         {
             Reader r = null;
-            User<? extends Principal> u = JsonUserReader.read(r);
+            JsonUserReader reader = new JsonUserReader();
+            User<? extends Principal> u = reader.read(r);
             fail("null Reader should throw IllegalArgumentException");
         }
         catch (IllegalArgumentException e) {}
@@ -130,7 +133,8 @@ public class JsonUserReaderWriterTest
     {
         try
         {
-            JsonUserWriter.write(null, new StringBuilder());
+            JsonUserWriter writer = new JsonUserWriter();
+            writer.write(null, new StringBuilder());
             fail("null User should throw WriterException");
         }
         catch (WriterException e) {}
@@ -140,16 +144,18 @@ public class JsonUserReaderWriterTest
     public void testReadWrite()
         throws Exception
     {
-        User<? extends Principal> expected = new User<Principal>(new HttpPrincipal("foo"));
+        User<Principal> expected = new User<Principal>(new HttpPrincipal("foo"));
         expected.getIdentities().add(new NumericPrincipal(123l));
         expected.details.add(new PersonalDetails("firstname", "lastname"));
         expected.details.add(new PosixDetails(123l, 456l, "foo"));
 
         StringBuilder json = new StringBuilder();
-        JsonUserWriter.write(expected, json);
+        JsonUserWriter writer = new JsonUserWriter();
+        writer.write(expected, json);
         assertFalse(json.toString().isEmpty());
-        
-        User<? extends Principal> actual = JsonUserReader.read(json.toString());
+
+        JsonUserReader reader = new JsonUserReader();
+        User<Principal> actual = reader.read(json.toString());
         assertNotNull(actual);
         assertEquals(expected, actual);
     }
diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserRequestReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserRequestReaderWriterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd4f6e715dd2a66723ed7a7d612806813b2dea00
--- /dev/null
+++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserRequestReaderWriterTest.java
@@ -0,0 +1,157 @@
+/*
+ ************************************************************************
+ *******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
+ **************  CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES  **************
+ *
+ *  (c) 2015.                            (c) 2015.
+ *  Government of Canada                 Gouvernement du Canada
+ *  National Research Council            Conseil national de recherches
+ *  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+ *  All rights reserved                  Tous droits réservés
+ *
+ *  NRC disclaims any warranties,        Le CNRC dénie toute garantie
+ *  expressed, implied, or               énoncée, implicite ou légale,
+ *  statutory, of any kind with          de quelque nature que ce
+ *  respect to the software,             soit, concernant le logiciel,
+ *  including without limitation         y compris sans restriction
+ *  any warranty of merchantability      toute garantie de valeur
+ *  or fitness for a particular          marchande ou de pertinence
+ *  purpose. NRC shall not be            pour un usage particulier.
+ *  liable in any event for any          Le CNRC ne pourra en aucun cas
+ *  damages, whether direct or           être tenu responsable de tout
+ *  indirect, special or general,        dommage, direct ou indirect,
+ *  consequential or incidental,         particulier ou général,
+ *  arising from the use of the          accessoire ou fortuit, résultant
+ *  software.  Neither the name          de l'utilisation du logiciel. Ni
+ *  of the National Research             le nom du Conseil National de
+ *  Council of Canada nor the            Recherches du Canada ni les noms
+ *  names of its contributors may        de ses  participants ne peuvent
+ *  be used to endorse or promote        être utilisés pour approuver ou
+ *  products derived from this           promouvoir les produits dérivés
+ *  software without specific prior      de ce logiciel sans autorisation
+ *  written permission.                  préalable et particulière
+ *                                       par écrit.
+ *
+ *  This file is part of the             Ce fichier fait partie du projet
+ *  OpenCADC project.                    OpenCADC.
+ *
+ *  OpenCADC is free software:           OpenCADC est un logiciel libre ;
+ *  you can redistribute it and/or       vous pouvez le redistribuer ou le
+ *  modify it under the terms of         modifier suivant les termes de
+ *  the GNU Affero General Public        la “GNU Affero General Public
+ *  License as published by the          License” telle que publiée
+ *  Free Software Foundation,            par la Free Software Foundation
+ *  either version 3 of the              : soit la version 3 de cette
+ *  License, or (at your option)         licence, soit (à votre gré)
+ *  any later version.                   toute version ultérieure.
+ *
+ *  OpenCADC is distributed in the       OpenCADC est distribué
+ *  hope that it will be useful,         dans l’espoir qu’il vous
+ *  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
+ *  without even the implied             GARANTIE : sans même la garantie
+ *  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILITÉ
+ *  or FITNESS FOR A PARTICULAR          ni d’ADÉQUATION À UN OBJECTIF
+ *  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
+ *  General Public License for           Générale Publique GNU Affero
+ *  more details.                        pour plus de détails.
+ *
+ *  You should have received             Vous devriez avoir reçu une
+ *  a copy of the GNU Affero             copie de la Licence Générale
+ *  General Public License along         Publique GNU Affero avec
+ *  with OpenCADC.  If not, see          OpenCADC ; si ce n’est
+ *  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
+ *                                       <http://www.gnu.org/licenses/>.
+ *
+ *
+ ************************************************************************
+ */
+package ca.nrc.cadc.ac.json;
+
+import ca.nrc.cadc.ac.PersonalDetails;
+import ca.nrc.cadc.ac.User;
+import ca.nrc.cadc.ac.UserRequest;
+import ca.nrc.cadc.ac.WriterException;
+import ca.nrc.cadc.auth.HttpPrincipal;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.security.Principal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+
+public class JsonUserRequestReaderWriterTest
+{
+    @Test
+    public void testReaderExceptions()
+        throws Exception
+    {
+        try
+        {
+            String s = null;
+            JsonUserRequestReader reader = new JsonUserRequestReader();
+            UserRequest u = reader.read(s);
+            fail("null String should throw IllegalArgumentException");
+        }
+        catch (IllegalArgumentException e) {}
+
+        try
+        {
+            InputStream in = null;
+            JsonUserRequestReader reader = new JsonUserRequestReader();
+            UserRequest u = reader.read(in);
+            fail("null InputStream should throw IOException");
+        }
+        catch (IOException e) {}
+
+        try
+        {
+            Reader r = null;
+            JsonUserRequestReader reader = new JsonUserRequestReader();
+            UserRequest u = reader.read(r);
+            fail("null Reader should throw IllegalArgumentException");
+        }
+        catch (IllegalArgumentException e) {}
+    }
+
+    @Test
+    public void testWriterExceptions()
+        throws Exception
+    {
+        try
+        {
+            JsonUserRequestWriter writer = new JsonUserRequestWriter();
+            writer.write(null, new StringBuilder());
+            fail("null User should throw WriterException");
+        }
+        catch (WriterException e) {}
+    }
+
+    @Test
+    public void testReadWrite()
+        throws Exception
+    {
+        User<Principal> expectedUser =
+            new User<Principal>(new HttpPrincipal("CADCtest"));
+        expectedUser.details.add(new PersonalDetails("CADCtest", "User"));
+
+        UserRequest<Principal> expected =
+            new UserRequest<Principal>(expectedUser, "MYPASSWORD".toCharArray());
+
+        StringBuilder json = new StringBuilder();
+        JsonUserRequestWriter writer = new JsonUserRequestWriter();
+        writer.write(expected, json);
+        assertFalse(json.toString().isEmpty());
+
+        JsonUserRequestReader reader = new JsonUserRequestReader();
+        UserRequest<Principal> actual = reader.read(json.toString());
+        assertNotNull(actual);
+        assertEquals(expected, actual);
+    }
+
+}
diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java
index 3c3dbe07116b1f1e3f2e41bfc49b39a12d2edb94..6aab545506a02e5be27e23a648289c284eef17a5 100644
--- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java
+++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java
@@ -70,6 +70,8 @@ package ca.nrc.cadc.ac.xml;
 
 import ca.nrc.cadc.ac.Group;
 import ca.nrc.cadc.ac.GroupProperty;
+import ca.nrc.cadc.ac.PersonalDetails;
+import ca.nrc.cadc.ac.PosixDetails;
 import ca.nrc.cadc.ac.User;
 import ca.nrc.cadc.ac.WriterException;
 import ca.nrc.cadc.auth.HttpPrincipal;
@@ -163,10 +165,24 @@ public class GroupReaderWriterTest
     public void testMaximalReadWrite()
         throws Exception
     {
-        Group expected = new Group("groupID", new User<Principal>(new HttpPrincipal("foo")));
+        User<Principal> owner = new User<Principal>(new HttpPrincipal("foo"));
+        X500Principal x500Principal = new X500Principal("cn=foo,o=bar");
+        owner.getIdentities().add(x500Principal);
+        PersonalDetails personalDetails = new PersonalDetails("foo", "bar");
+        personalDetails.address = "address";
+        personalDetails.email = "email";
+        personalDetails.institute = "institute";
+        personalDetails.city = "city";
+        personalDetails.country = "country";
+        owner.details.add(personalDetails);
+        PosixDetails posixDetails = new PosixDetails(123L, 456L, "/dev/null");
+        owner.details.add(posixDetails);
+
+        Group expected = new Group("groupID", owner);
         expected.description = "description";
         expected.lastModified = new Date();
-        expected.getProperties().add(new GroupProperty("key", "value", true));
+        expected.getProperties().add(new GroupProperty("key1", "value1", true));
+        expected.getProperties().add(new GroupProperty("key2", "value2", false));
         
         Group groupMember = new Group("member", new User<Principal>(new OpenIdPrincipal("bar")));
         User<Principal> userMember = new User<Principal>(new HttpPrincipal("baz"));