From 87b6d604b567cf5c7368b3a5cdeda640a8c537da Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Fri, 15 Jun 2012 08:47:53 +0000
Subject: [PATCH] SP-128 / BIS-14 Query Plugins in JSON-RPC - improve unit
 tests

SVN: 25724
---
 .../api/server/json/common/JsonConstants.java |    7 +
 .../JsonTypeAndClassSerializer.java           |  109 ++
 ...sonTypeAndClassAnnotationIntrospector.java |   11 +
 .../serializer/JsonSerializerFactory.java     |   22 +-
 .../server/json/JsonDeserializationTest.java  | 1077 +++--------------
 .../server/json/JsonSerializationTest.java    |  390 +-----
 .../api/server/json/JsonTestObjectMapper.java |   39 +-
 .../api/server/json/common/ObjectCounter.java |   42 +
 .../api/server/json/common/ObjectMap.java     |   81 ++
 .../api/server/json/common/ObjectType.java    |   27 +
 .../json/object/ObjectWithContainerTypes.java |  311 ++++-
 .../json/object/ObjectWithDateTypes.java      |   59 +-
 .../json/object/ObjectWithEnumTypes.java      |   59 +-
 .../object/ObjectWithIgnoredProperties.java   |   76 +-
 .../json/object/ObjectWithNestedTypes.java    |  126 +-
 .../json/object/ObjectWithPrimitiveTypes.java |   83 +-
 .../json/object/ObjectWithPrivateAccess.java  |   42 +-
 .../object/ObjectWithRenamedProperties.java   |   67 +-
 .../server/json/object/ObjectWithType.java    |   42 +-
 .../server/json/object/ObjectWithTypeA.java   |   46 +-
 .../server/json/object/ObjectWithTypeAA.java  |   49 +-
 .../object/ObjectWithTypeALegalDuplicate.java |    3 +-
 .../server/json/object/ObjectWithTypeB.java   |   46 +-
 .../ObjectWithTypeBIllegalDuplicate.java      |    3 +-
 .../object/ObjectWithTypeButNoSubtypes.java   |   49 +-
 .../server/json/object/ObjectWithTypeC.java   |   46 +-
 .../json/object/ObjectWithUnknownType.java    |   55 +
 27 files changed, 1671 insertions(+), 1296 deletions(-)
 create mode 100644 openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonTypeAndClassSerializer.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectCounter.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java

diff --git a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/common/JsonConstants.java b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/common/JsonConstants.java
index e5226cefd45..8d3e9588ff5 100644
--- a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/common/JsonConstants.java
+++ b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/common/JsonConstants.java
@@ -22,12 +22,19 @@ package ch.systemsx.cisd.common.api.server.json.common;
 public class JsonConstants
 {
 
+    private static final String ID_FIELD = "@id";
+
     private static final String TYPE_FIELD = "@type";
 
     private static final String LEGACY_CLASS_FIELD = "@class";
 
     private static final String CLASSES_PREFIX = "ch.systemsx";
 
+    public static final String getIdField()
+    {
+        return ID_FIELD;
+    }
+
     public static final String getTypeField()
     {
         return TYPE_FIELD;
diff --git a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonTypeAndClassSerializer.java b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonTypeAndClassSerializer.java
new file mode 100644
index 00000000000..9b3040f061f
--- /dev/null
+++ b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonTypeAndClassSerializer.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.api.server.json.deserializer;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
+import com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeSerializer;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+public class JsonTypeAndClassSerializer extends AsPropertyTypeSerializer
+{
+
+    public JsonTypeAndClassSerializer(TypeIdResolver idRes, BeanProperty property, String propName)
+    {
+        super(idRes, property, propName);
+    }
+
+    @Override
+    public JsonTypeAndClassSerializer forProperty(BeanProperty prop)
+    {
+        if (_property == prop)
+            return this;
+        return new JsonTypeAndClassSerializer(this._idResolver, prop, this._typePropertyName);
+    }
+
+    @Override
+    public void writeTypePrefixForObject(Object value, JsonGenerator jgen) throws IOException,
+            JsonProcessingException
+    {
+        if (isValueWithType(value))
+        {
+            jgen.writeStartObject();
+            jgen.writeStringField(_typePropertyName, idFromValue(value));
+        } else
+        {
+            jgen.writeStartObject();
+        }
+    }
+
+    @Override
+    public void writeTypeSuffixForObject(Object value, JsonGenerator jgen) throws IOException,
+            JsonProcessingException
+    {
+        jgen.writeEndObject();
+    }
+
+    @Override
+    public void writeTypePrefixForScalar(Object value, JsonGenerator jgen) throws IOException,
+            JsonProcessingException
+    {
+        if (isValueWithType(value))
+        {
+            super.writeTypePrefixForScalar(value, jgen);
+        }
+    }
+
+    @Override
+    public void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) throws IOException,
+            JsonProcessingException
+    {
+        if (isValueWithType(value))
+        {
+            super.writeTypeSuffixForScalar(value, jgen);
+        }
+    }
+
+    @Override
+    public void writeTypePrefixForArray(Object value, JsonGenerator jgen) throws IOException,
+            JsonProcessingException
+    {
+        jgen.writeStartArray();
+    }
+
+    @Override
+    public void writeTypeSuffixForArray(Object value, JsonGenerator jgen) throws IOException,
+            JsonProcessingException
+    {
+        jgen.writeEndArray();
+    }
+
+    private boolean isValueWithType(Object value)
+    {
+        return value != null && value.getClass().isAnnotationPresent(JsonObject.class)
+                && !value.getClass().isEnum();
+    }
+
+}
diff --git a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java
index 0d48932df94..449d9f76e50 100644
--- a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java
+++ b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java
@@ -19,13 +19,17 @@ package ch.systemsx.cisd.common.api.server.json.introspector;
 import java.util.HashMap;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.JsonConstants;
 import ch.systemsx.cisd.common.api.server.json.mapping.IJsonClassValueToClassObjectsMapping;
 import ch.systemsx.cisd.common.api.server.json.resolver.JsonTypeAndClassResolverBuilder;
 
@@ -54,6 +58,13 @@ public class JsonTypeAndClassAnnotationIntrospector extends JacksonAnnotationInt
         return (tn == null) ? null : tn.value();
     }
 
+    @Override
+    public ObjectIdInfo findObjectIdInfo(Annotated ann)
+    {
+        return new ObjectIdInfo(JsonConstants.getIdField(), Object.class,
+                ObjectIdGenerators.IntSequenceGenerator.class);
+    }
+
     @Override
     public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config, AnnotatedClass ac,
             JavaType baseType)
diff --git a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/serializer/JsonSerializerFactory.java b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/serializer/JsonSerializerFactory.java
index 96a01ad9c1e..efb448e3bb1 100644
--- a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/serializer/JsonSerializerFactory.java
+++ b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/serializer/JsonSerializerFactory.java
@@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
 import com.fasterxml.jackson.databind.jsontype.NamedType;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
-import com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeSerializer;
 import com.fasterxml.jackson.databind.jsontype.impl.TypeNameIdResolver;
 import com.fasterxml.jackson.databind.ser.BeanSerializerFactory;
 import com.fasterxml.jackson.databind.type.ArrayType;
@@ -38,6 +37,7 @@ import com.fasterxml.jackson.databind.type.MapType;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.common.api.server.json.common.JsonConstants;
+import ch.systemsx.cisd.common.api.server.json.deserializer.JsonTypeAndClassSerializer;
 
 /**
  * @author pkupczyk
@@ -55,10 +55,10 @@ public class JsonSerializerFactory extends BeanSerializerFactory
             BeanDescription beanDesc, boolean staticTyping, TypeSerializer elementTypeSerializer,
             JsonSerializer<Object> elementValueSerializer) throws JsonMappingException
     {
-        ArrayType newType =
-                type.withContentTypeHandler(createContentTypeSerializer(config, type, null));
+        TypeSerializer newTypeSerializer = createContentTypeSerializer(config, type, null);
+        ArrayType newType = type.withContentTypeHandler(newTypeSerializer);
         return super.buildArraySerializer(config, newType, beanDesc, staticTyping,
-                elementTypeSerializer, elementValueSerializer);
+                newTypeSerializer, elementValueSerializer);
     }
 
     @Override
@@ -67,10 +67,10 @@ public class JsonSerializerFactory extends BeanSerializerFactory
             boolean staticTyping, TypeSerializer elementTypeSerializer,
             JsonSerializer<Object> elementValueSerializer) throws JsonMappingException
     {
-        CollectionType newType =
-                type.withContentTypeHandler(createContentTypeSerializer(config, type, property));
+        TypeSerializer newTypeSerializer = createContentTypeSerializer(config, type, property);
+        CollectionType newType = type.withContentTypeHandler(newTypeSerializer);
         return super.buildCollectionSerializer(config, newType, beanDesc, property, staticTyping,
-                elementTypeSerializer, elementValueSerializer);
+                newTypeSerializer, elementValueSerializer);
     }
 
     @Override
@@ -79,10 +79,10 @@ public class JsonSerializerFactory extends BeanSerializerFactory
             TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer)
             throws JsonMappingException
     {
-        MapType newType =
-                type.withContentTypeHandler(createContentTypeSerializer(config, type, null));
+        TypeSerializer newTypeSerializer = createContentTypeSerializer(config, type, null);
+        MapType newType = type.withContentTypeHandler(newTypeSerializer);
         return super.buildMapSerializer(config, newType, beanDesc, staticTyping, keySerializer,
-                elementTypeSerializer, elementValueSerializer);
+                newTypeSerializer, elementValueSerializer);
     }
 
     private TypeSerializer createContentTypeSerializer(SerializationConfig config,
@@ -106,7 +106,7 @@ public class JsonSerializerFactory extends BeanSerializerFactory
                     config.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai);
             TypeIdResolver resolver =
                     TypeNameIdResolver.construct(config, contentType, subtypes, true, false);
-            return new AsPropertyTypeSerializer(resolver, property, JsonConstants.getTypeField());
+            return new JsonTypeAndClassSerializer(resolver, property, JsonConstants.getTypeField());
         } else
         {
             return null;
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java
index 8eaee1d809e..9c1c43fc66c 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java
@@ -17,14 +17,7 @@
 package ch.systemsx.cisd.common.api.server.json;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.EnumSet;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -34,10 +27,11 @@ import org.testng.annotations.Test;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypes;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithDateTypes;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes.NestedEnum;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithIgnoredProperties;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested;
@@ -63,1150 +57,465 @@ public class JsonDeserializationTest
     @Test
     public void testDeserializeJsonWithRootTypeToRootInterface1() throws Exception
     {
-        testDeserializeObjectWithType(true, false, ObjectWithTypeInterface1.class);
-        testDeserializeObjectWithType(false, true, ObjectWithTypeInterface1.class);
+        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithTypeInterface1.class);
+        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithTypeInterface1.class);
     }
 
     @Test
     public void testDeserializeJsonWithRootTypeToRootInterface2() throws Exception
     {
-        testDeserializeObjectWithType(true, false, ObjectWithTypeInterface2.class);
-        testDeserializeObjectWithType(false, true, ObjectWithTypeInterface2.class);
+        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithTypeInterface2.class);
+        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithTypeInterface2.class);
     }
 
     @Test
     public void testDeserializeJsonWithRootTypeToRootType() throws Exception
     {
-        testDeserializeObjectWithType(true, false, ObjectWithType.class);
-        testDeserializeObjectWithType(false, true, ObjectWithType.class);
+        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithType.class);
+        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToRootInterface1() throws Exception
     {
-        testDeserializeObjectWithTypeA(true, false, ObjectWithTypeInterface1.class);
-        testDeserializeObjectWithTypeA(false, true, ObjectWithTypeInterface1.class);
+        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeInterface1.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeInterface1.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToRootInterface2() throws Exception
     {
-        testDeserializeObjectWithTypeA(true, false, ObjectWithTypeInterface2.class);
-        testDeserializeObjectWithTypeA(false, true, ObjectWithTypeInterface2.class);
+        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeInterface2.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeInterface2.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToRootType() throws Exception
     {
-        testDeserializeObjectWithTypeA(true, false, ObjectWithType.class);
-        testDeserializeObjectWithTypeA(false, true, ObjectWithType.class);
+        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithType.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToFirstLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeA(true, false, ObjectWithTypeA.class);
-        testDeserializeObjectWithTypeA(false, true, ObjectWithTypeA.class);
+        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeA.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeA.class);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithFirstLevelSubTypeToSecondLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeA(true, false, ObjectWithTypeAA.class);
-        testDeserializeObjectWithTypeA(false, true, ObjectWithTypeAA.class);
+        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeAA.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeAA.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToRootInterface1() throws Exception
     {
-        testDeserializeObjectWithTypeAA(true, false, ObjectWithTypeInterface1.class);
-        testDeserializeObjectWithTypeAA(false, true, ObjectWithTypeInterface1.class);
+        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeInterface1.class);
+        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeInterface1.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToRootInterface2() throws Exception
     {
-        testDeserializeObjectWithTypeAA(true, false, ObjectWithTypeInterface2.class);
-        testDeserializeObjectWithTypeAA(false, true, ObjectWithTypeInterface2.class);
+        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeInterface2.class);
+        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeInterface2.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToRootType() throws Exception
     {
-        testDeserializeObjectWithTypeAA(true, false, ObjectWithType.class);
-        testDeserializeObjectWithTypeAA(false, true, ObjectWithType.class);
+        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithType.class);
+        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToFirstLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeAA(true, false, ObjectWithTypeA.class);
-        testDeserializeObjectWithTypeAA(false, true, ObjectWithTypeA.class);
+        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeA.class);
+        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeA.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToSecondLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeAA(true, false, ObjectWithTypeAA.class);
-        testDeserializeObjectWithTypeAA(false, true, ObjectWithTypeAA.class);
+        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeAA.class);
+        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeAA.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedRootTypeToNestedRootType() throws Exception
     {
-        testDeserializeObjectNested(true, false, ObjectNested.class);
-        testDeserializeObjectNested(false, true, ObjectNested.class);
+        testDeserializeObjectNested(ObjectType.TYPE, ObjectNested.class);
+        testDeserializeObjectNested(ObjectType.CLASS, ObjectNested.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedSubTypeToNestedRootType() throws Exception
     {
-        testDeserializeObjectNestedChild(true, false, ObjectNested.class);
-        testDeserializeObjectNestedChild(false, true, ObjectNested.class);
+        testDeserializeObjectNestedChild(ObjectType.TYPE, ObjectNested.class);
+        testDeserializeObjectNestedChild(ObjectType.CLASS, ObjectNested.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedSubTypeToNestedSubType() throws Exception
     {
-        testDeserializeObjectNestedChild(true, false, ObjectNestedChild.class);
-        testDeserializeObjectNestedChild(false, true, ObjectNestedChild.class);
+        testDeserializeObjectNestedChild(ObjectType.TYPE, ObjectNestedChild.class);
+        testDeserializeObjectNestedChild(ObjectType.CLASS, ObjectNestedChild.class);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithPrimitiveTypes() throws Exception
     {
-        testDeserializeObjectWithPrimitiveTypes(true, false);
-        testDeserializeObjectWithPrimitiveTypes(false, true);
+        testDeserializeObjectWithPrimitiveTypes(ObjectType.TYPE);
+        testDeserializeObjectWithPrimitiveTypes(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithNestedTypes() throws Exception
     {
-        testDeserializeObjectWithNestedTypes(true, false);
-        testDeserializeObjectWithNestedTypes(false, true);
+        testDeserializeObjectWithNestedTypes(ObjectType.TYPE);
+        testDeserializeObjectWithNestedTypes(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithEnumTypes() throws Exception
     {
-        testDeserializeObjectWithEnumTypes(true, false);
-        testDeserializeObjectWithEnumTypes(false, true);
+        testDeserializeObjectWithEnumTypes(ObjectType.TYPE);
+        testDeserializeObjectWithEnumTypes(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithDateTypes() throws Exception
     {
-        testDeserializeObjectWithDateTypes(true, false);
-        testDeserializeObjectWithDateTypes(false, true);
+        testDeserializeObjectWithDateTypes(ObjectType.TYPE);
+        testDeserializeObjectWithDateTypes(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithContainerTypes() throws Exception
     {
-        testDeserializeObjectWithContainerTypes(true, false);
-        testDeserializeObjectWithContainerTypes(false, true);
+        testDeserializeObjectWithContainerTypes(ObjectType.TYPE);
+        testDeserializeObjectWithContainerTypes(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithIgnoredProperties() throws Exception
     {
-        testDeserializeObjectWithIgnoredProperties(true, false);
-        testDeserializeObjectWithIgnoredProperties(false, true);
+        testDeserializeObjectWithIgnoredProperties(ObjectType.TYPE);
+        testDeserializeObjectWithIgnoredProperties(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithRenamedProperties() throws Exception
     {
-        testDeserializeObjectWithRenamedProperties(true, false);
-        testDeserializeObjectWithRenamedProperties(false, true);
+        testDeserializeObjectWithRenamedProperties(ObjectType.TYPE);
+        testDeserializeObjectWithRenamedProperties(ObjectType.CLASS);
     }
 
     @Test
     public void testDeserializeJsonWithPrivateAccess() throws Exception
     {
-        testDeserializeObjectWithPrivateAccess(true, false);
-        testDeserializeObjectWithPrivateAccess(false, true);
+        testDeserializeObjectWithPrivateAccess(ObjectType.TYPE);
+        testDeserializeObjectWithPrivateAccess(ObjectType.CLASS);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithoutTypeToPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithType(false, false, ObjectWithType.class);
+        testDeserializeObjectWithType(ObjectType.NONE, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithTypeToPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithType(true, false, ObjectWithType.class);
-        testDeserializeObjectWithType(false, true, ObjectWithType.class);
+        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithType.class);
+        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithoutTypeToNotPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithTypeButNoSubtypes(false, false, ObjectWithTypeButNoSubtypes.class);
+        testDeserializeObjectWithTypeButNoSubtypes(ObjectType.NONE,
+                ObjectWithTypeButNoSubtypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithTypeToNotPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithTypeButNoSubtypes(true, false, ObjectWithTypeButNoSubtypes.class);
-        testDeserializeObjectWithTypeButNoSubtypes(false, true, ObjectWithTypeButNoSubtypes.class);
+        testDeserializeObjectWithTypeButNoSubtypes(ObjectType.TYPE,
+                ObjectWithTypeButNoSubtypes.class);
+        testDeserializeObjectWithTypeButNoSubtypes(ObjectType.CLASS,
+                ObjectWithTypeButNoSubtypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithLegacyClassDefinedInClassMapping() throws Exception
     {
-        testDeserializeObjectWithTypeA(false, true, ObjectWithType.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithType.class);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithLegacyClassNotDefinedInClassMapping() throws Exception
     {
-        testDeserializeObjectWithTypeC(false, true, ObjectWithType.class);
+        testDeserializeObjectWithTypeC(ObjectType.CLASS, ObjectWithType.class);
     }
 
     @Test(expectedExceptions = Exception.class)
     public void testDeserializeJsonWithLegacyClassNotDefinedInClassMappingButMatchingType()
             throws Exception
     {
-        Map<String, Object> map = createObjectWithTypeC(false, false);
-        map.put("@class", ".ObjectWithTypeC");
-        deserialize(map, ObjectWithTypeC.class);
+        ObjectMap map = ObjectWithTypeC.createMap(null, ObjectType.NONE);
+        map.putType(null, ".ObjectWithTypeC", ObjectType.CLASS);
+        deserialize(map.toMap(), ObjectWithTypeC.class);
     }
 
     @Test
     public void testDeserializeJsonWithNotUniqueLegacyClassUsedInDifferentInheritanceTrees()
             throws Exception
     {
-        testDeserializeObjectWithTypeA(false, true, ObjectWithType.class);
+        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithType.class);
     }
 
-    @Test(expectedExceptions = Exception.class)
+    @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithNotUniqueLegacyClassUsedInSameInheritanceTree()
             throws Exception
     {
-        testDeserializeObjectWithTypeB(false, true, ObjectWithType.class);
+        ObjectMap map = ObjectWithTypeB.createMap(null, ObjectType.CLASS);
+        deserialize(map.toMap(), ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithNotUniqueTypeUsedInDifferentInheritanceTrees()
             throws Exception
     {
-        testDeserializeObjectWithTypeA(true, false, ObjectWithType.class);
+        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithType.class);
     }
 
-    @Test(expectedExceptions = Exception.class)
+    @Test
     public void testDeserializeJsonWithNotUniqueTypeUsedInSameInheritanceTree() throws Exception
     {
-        testDeserializeObjectWithTypeB(true, false, ObjectWithType.class);
+        ObjectMap map = ObjectWithTypeB.createMap(null, ObjectType.TYPE);
+        Object result = deserialize(map.toMap(), ObjectWithType.class);
+        Assert.assertFalse(ObjectWithTypeB.class.equals(result.getClass()));
     }
 
     @Test
     public void testDeserializeJsonWithNestedMapsInCollection() throws Exception
     {
-        testDeserializeJsonWithNestedMapsInCollection(true, false);
-        testDeserializeJsonWithNestedMapsInCollection(false, true);
+        testDeserializeJsonWithNestedMapsInCollection(ObjectType.TYPE);
+        testDeserializeJsonWithNestedMapsInCollection(ObjectType.CLASS);
     }
 
-    private void testDeserializeJsonWithNestedMapsInCollection(boolean includeType,
-            boolean includeClass) throws Exception
+    private void testDeserializeJsonWithNestedMapsInCollection(ObjectType includeType)
+            throws Exception
     {
-        Collection<Object> collection = new ArrayList<Object>();
-        collection.add(createObjectWithContainerTypes(includeType, includeClass));
+        ObjectWithContainerTypes object =
+                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
+        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
+
+        List<Object> collectionWithObject = new ArrayList<Object>();
+        collectionWithObject.add(object);
 
-        Collection<Object> collectionResult = deserialize(collection, Collection.class);
+        List<Object> collectionWithMap = new ArrayList<Object>();
+        collectionWithMap.add(map.toMap());
 
-        Assert.assertEquals(collectionResult.size(), 1);
-        assertObjectWithContainerTypes(collectionResult.iterator().next());
+        Object result = deserialize(collectionWithMap, List.class);
+        Assert.assertTrue(collectionWithObject.equals(result));
     }
 
     @Test
     public void testDeserializeJsonWithNestedMapsInMap() throws Exception
     {
-        testDeserializeJsonWithNestedMapsInMap(true, false);
-        testDeserializeJsonWithNestedMapsInMap(false, true);
+        testDeserializeJsonWithNestedMapsInMap(ObjectType.TYPE);
+        testDeserializeJsonWithNestedMapsInMap(ObjectType.CLASS);
     }
 
-    private void testDeserializeJsonWithNestedMapsInMap(boolean includeType, boolean includeClass)
-            throws Exception
+    private void testDeserializeJsonWithNestedMapsInMap(ObjectType includeType) throws Exception
     {
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("objectWithContainerTypes",
-                createObjectWithContainerTypes(includeType, includeClass));
+        ObjectWithContainerTypes object =
+                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
+        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
 
-        HashMap<String, Object> mapResult = deserialize(map, Map.class);
+        Map<String, Object> mapWithObject = new HashMap<String, Object>();
+        mapWithObject.put("object", object);
 
-        Assert.assertEquals(mapResult.size(), 1);
-        assertObjectWithContainerTypes(mapResult.get("objectWithContainerTypes"));
+        Map<String, Object> mapWithMap = new HashMap<String, Object>();
+        mapWithMap.put("object", map.toMap());
+
+        Object result = deserialize(mapWithMap, Map.class);
+        Assert.assertTrue(mapWithObject.equals(result));
     }
 
     @Test
     public void testDeserializeJsonWithNestedMapsInList() throws Exception
     {
-        testDeserializeJsonWithNestedMapsInList(true, false);
-        testDeserializeJsonWithNestedMapsInList(false, true);
-    }
-
-    private void testDeserializeJsonWithNestedMapsInList(boolean includeType, boolean includeClass)
-            throws Exception
-    {
-        List<Object> list = new ArrayList<Object>();
-        list.add(createObjectWithContainerTypes(includeType, includeClass));
-
-        List<Object> listResult = deserialize(list, List.class);
-
-        Assert.assertEquals(listResult.size(), 1);
-        assertObjectWithContainerTypes(listResult.get(0));
-    }
-
-    private void testDeserializeObjectWithType(boolean includeType, boolean includeClass,
-            Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithType(includeType, includeClass);
-
-        Object object = deserialize(map, rootClass);
-
-        assertObjectWithType(object);
-    }
-
-    private void testDeserializeObjectWithTypeA(boolean includeType, boolean includeClass,
-            Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithTypeA(includeType, includeClass);
-
-        ObjectWithTypeA object = deserialize(map, rootClass);
-
-        assertObjectWithTypeA(object);
-    }
-
-    private void testDeserializeObjectWithTypeB(boolean includeType, boolean includeClass,
-            Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithTypeB(includeType, includeClass);
-
-        ObjectWithTypeB object = deserialize(map, rootClass);
-
-        assertObjectWithTypeB(object);
-    }
-
-    private void testDeserializeObjectWithTypeC(boolean includeType, boolean includeClass,
-            Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithTypeC(includeType, includeClass);
-
-        ObjectWithTypeC object = deserialize(map, rootClass);
-
-        assertObjectWithTypeC(object);
-    }
-
-    private void testDeserializeObjectWithTypeAA(boolean includeType, boolean includeClass,
-            Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithTypeAA(includeType, includeClass);
-
-        ObjectWithTypeAA object = deserialize(map, rootClass);
-
-        assertObjectWithTypeAA(object);
-    }
-
-    private void testDeserializeObjectWithTypeButNoSubtypes(boolean includeType,
-            boolean includeClass, Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithTypeButNoSubtypes(includeType, includeClass);
-
-        ObjectWithTypeButNoSubtypes object = deserialize(map, rootClass);
-
-        assertObjectWithTypeButNoSubtypes(object);
-    }
-
-    private void testDeserializeObjectWithIgnoredProperties(boolean includeType,
-            boolean includeClass) throws Exception
-    {
-        Map<String, Object> map = createObjectWithIgnoredProperties(includeType, includeClass);
-
-        ObjectWithIgnoredProperties object = deserialize(map, ObjectWithIgnoredProperties.class);
-
-        assertObjectWithIgnoredProperties(object);
+        testDeserializeJsonWithNestedMapsInList(ObjectType.TYPE);
+        testDeserializeJsonWithNestedMapsInList(ObjectType.CLASS);
     }
 
-    private void testDeserializeObjectWithRenamedProperties(boolean includeType,
-            boolean includeClass) throws Exception
+    private void testDeserializeJsonWithNestedMapsInList(ObjectType includeType) throws Exception
     {
-        Map<String, Object> map = createObjectWithRenamedProperties(includeType, includeClass);
+        ObjectWithContainerTypes object =
+                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
+        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
 
-        ObjectWithRenamedProperties object = deserialize(map, ObjectWithRenamedProperties.class);
+        List<Object> listWithObject = new ArrayList<Object>();
+        listWithObject.add(object);
 
-        assertObjectWithRenamedProperties(object);
-    }
+        List<Object> listWithMap = new ArrayList<Object>();
+        listWithMap.add(map.toMap());
 
-    private void testDeserializeObjectWithPrivateAccess(boolean includeType, boolean includeClass)
-            throws Exception
-    {
-        Map<String, Object> map = createObjectWithPrivateAccess(includeType, includeClass);
-
-        ObjectWithPrivateAccess object = deserialize(map, ObjectWithPrivateAccess.class);
-
-        assertObjectWithPrivateAccess(object);
+        Object result = deserialize(listWithMap, List.class);
+        Assert.assertTrue(listWithObject.equals(result));
     }
 
-    private void testDeserializeObjectWithPrimitiveTypes(boolean includeType, boolean includeClass)
+    private void testDeserializeObjectWithType(ObjectType includeType, Class<?> rootClass)
             throws Exception
     {
-        Map<String, Object> map = createObjectWithPrimitiveTypes(includeType, includeClass);
+        ObjectWithType object = ObjectWithType.createObject();
+        ObjectMap map = ObjectWithType.createMap(null, includeType);
 
-        ObjectWithPrimitiveTypes object = deserialize(map, ObjectWithPrimitiveTypes.class);
-
-        assertObjectWithPrimitiveTypes(object);
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void testDeserializeObjectWithEnumTypes(boolean includeType, boolean includeClass)
+    private void testDeserializeObjectWithTypeA(ObjectType includeType, Class<?> rootClass)
             throws Exception
     {
-        Map<String, Object> map = createObjectWithEnumTypes(includeType, includeClass);
-
-        ObjectWithEnumTypes object = deserialize(map, ObjectWithEnumTypes.class);
+        ObjectWithTypeA object = ObjectWithTypeA.createObject();
+        ObjectMap map = ObjectWithTypeA.createMap(null, includeType);
 
-        assertObjectWithEnumTypes(object);
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void testDeserializeObjectWithDateTypes(boolean includeType, boolean includeClass)
+    private void testDeserializeObjectWithTypeC(ObjectType includeType, Class<?> rootClass)
             throws Exception
     {
-        Map<String, Object> map = createObjectWithDateTypes(includeType, includeClass);
-
-        ObjectWithDateTypes object = deserialize(map, ObjectWithDateTypes.class);
+        ObjectWithTypeC object = ObjectWithTypeC.createObject();
+        ObjectMap map = ObjectWithTypeC.createMap(null, includeType);
 
-        assertObjectWithDateTypes(object);
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void testDeserializeObjectWithContainerTypes(boolean includeType, boolean includeClass)
+    private void testDeserializeObjectWithTypeAA(ObjectType includeType, Class<?> rootClass)
             throws Exception
     {
-        Map<String, Object> map = createObjectWithContainerTypes(includeType, includeClass);
+        ObjectWithTypeAA object = ObjectWithTypeAA.createObject();
+        ObjectMap map = ObjectWithTypeAA.createMap(null, includeType);
 
-        ObjectWithContainerTypes object = deserialize(map, ObjectWithContainerTypes.class);
-
-        assertObjectWithContainerTypes(object);
-    }
-
-    private void testDeserializeObjectWithNestedTypes(boolean includeType, boolean includeClass)
-            throws Exception
-    {
-        Map<String, Object> map = createObjectWithNestedTypes(includeType, includeClass);
-
-        ObjectWithNestedTypes object = deserialize(map, ObjectWithNestedTypes.class);
-
-        assertObjectWithNestedTypes(object);
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void testDeserializeObjectNested(boolean includeType, boolean includeClass,
+    private void testDeserializeObjectWithTypeButNoSubtypes(ObjectType includeType,
             Class<?> rootClass) throws Exception
     {
-        Map<String, Object> objectMap = createObjectNested(includeType, includeClass);
-
-        ObjectNested object = deserialize(objectMap, rootClass);
+        ObjectWithTypeButNoSubtypes object = ObjectWithTypeButNoSubtypes.createObject();
+        ObjectMap map = ObjectWithTypeButNoSubtypes.createMap(null, includeType);
 
-        assertObjectNested(object);
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void testDeserializeObjectNestedChild(boolean includeType, boolean includeClass,
-            Class<?> rootClass) throws Exception
-    {
-        Map<String, Object> objectMap = createObjectNestedChild(includeType, includeClass);
-
-        ObjectNestedChild object = deserialize(objectMap, rootClass);
-
-        assertObjectNestedChild(object);
-    }
-
-    private Map<String, Object> createObjectWithType(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithType");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithType");
-        }
-        map.put("base", "baseValue");
-        return map;
-    }
-
-    private void assertObjectWithType(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithType.class);
-        ObjectWithType casted = (ObjectWithType) object;
-        Assert.assertEquals(casted.base, "baseValue");
-    }
-
-    private Map<String, Object> createObjectWithTypeA(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithTypeA");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithTypeA");
-        }
-        map.put("base", "baseValue");
-        map.put("a", "aValue");
-        return map;
-    }
-
-    private void assertObjectWithTypeA(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithTypeA.class);
-        ObjectWithTypeA casted = (ObjectWithTypeA) object;
-        Assert.assertEquals(casted.base, "baseValue");
-        Assert.assertEquals(casted.a, "aValue");
-    }
-
-    private Map<String, Object> createObjectWithTypeB(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithTypeB");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithTypeB");
-        }
-        map.put("base", "baseValue");
-        map.put("b", "bValue");
-        return map;
-    }
-
-    private void assertObjectWithTypeB(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithTypeB.class);
-        ObjectWithTypeB casted = (ObjectWithTypeB) object;
-        Assert.assertEquals(casted.base, "baseValue");
-        Assert.assertEquals(casted.b, "bValue");
-    }
-
-    private Map<String, Object> createObjectWithTypeC(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithTypeC");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithTypeC");
-        }
-        map.put("base", "baseValue");
-        map.put("c", "cValue");
-        return map;
-    }
-
-    private void assertObjectWithTypeC(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithTypeC.class);
-        ObjectWithTypeC casted = (ObjectWithTypeC) object;
-        Assert.assertEquals(casted.base, "baseValue");
-        Assert.assertEquals(casted.c, "cValue");
-    }
-
-    private Map<String, Object> createObjectWithTypeAA(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithTypeAA");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithTypeAA");
-        }
-        map.put("base", "baseValue");
-        map.put("a", "aValue");
-        map.put("aa", "aaValue");
-        return map;
-    }
-
-    private void assertObjectWithTypeAA(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithTypeAA.class);
-        ObjectWithTypeAA casted = (ObjectWithTypeAA) object;
-        Assert.assertEquals(casted.base, "baseValue");
-        Assert.assertEquals(casted.a, "aValue");
-        Assert.assertEquals(casted.aa, "aaValue");
-    }
-
-    private Map<String, Object> createObjectWithTypeButNoSubtypes(boolean includeType,
-            boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithTypeButNoSubtypes");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithTypeButNoSubtypes");
-        }
-        map.put("a", "aValue");
-        map.put("b", "bValue");
-        return map;
-    }
-
-    private void assertObjectWithTypeButNoSubtypes(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithTypeButNoSubtypes.class);
-        ObjectWithTypeButNoSubtypes casted = (ObjectWithTypeButNoSubtypes) object;
-        Assert.assertEquals(casted.a, "aValue");
-        Assert.assertEquals(casted.b, "bValue");
-    }
-
-    private Map<String, Object> createObjectWithIgnoredProperties(boolean includeType,
-            boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithIgnoredProperties");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithIgnoredProperties");
-        }
-        map.put("property", "propertyValue");
-        map.put("propertyWithGetterAndSetter", "propertyWithGetterAndSetterValue");
-        map.put("propertyIgnored", "propertyIgnoredValue");
-        map.put("propertyWithGetterAndSetterIgnored", "propertyWithGetterAndSetterIgnoredValue");
-        return map;
-    }
-
-    private void assertObjectWithIgnoredProperties(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithIgnoredProperties.class);
-        ObjectWithIgnoredProperties casted = (ObjectWithIgnoredProperties) object;
-        Assert.assertEquals(casted.property, "propertyValue");
-        Assert.assertEquals(casted.getPropertyWithGetterAndSetter(),
-                "propertyWithGetterAndSetterValue");
-        Assert.assertNull(casted.propertyIgnored);
-        Assert.assertNull(casted.getPropertyWithGetterAndSetterIgnored());
-    }
-
-    private Map<String, Object> createObjectWithRenamedProperties(boolean includeType,
-            boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithRenamedProperties");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithRenamedProperties");
-        }
-        map.put("property", "propertyValue");
-        map.put("propertyWithGetterAndSetter", "propertyWithGetterAndSetterValue");
-        map.put("propertyRenamed", "propertyRenamedValue");
-        map.put("propertyWithGetterAndSetterRenamed", "propertyWithGetterAndSetterRenamedValue");
-        return map;
-    }
-
-    private void assertObjectWithRenamedProperties(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithRenamedProperties.class);
-        ObjectWithRenamedProperties casted = (ObjectWithRenamedProperties) object;
-        Assert.assertEquals(casted.property, "propertyValue");
-        Assert.assertEquals(casted.getPropertyWithGetterAndSetter(),
-                "propertyWithGetterAndSetterValue");
-        Assert.assertEquals(casted.x, "propertyRenamedValue");
-        Assert.assertEquals(casted.getY(), "propertyWithGetterAndSetterRenamedValue");
-    }
-
-    private Map<String, Object> createObjectWithPrivateAccess(boolean includeType,
-            boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithPrivateAccess");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithPrivateAccess");
-        }
-        map.put("field", "fieldValue");
-        return map;
-    }
-
-    private void assertObjectWithPrivateAccess(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithPrivateAccess.class);
-        ObjectWithPrivateAccess casted = (ObjectWithPrivateAccess) object;
-        Assert.assertEquals(casted.getField(), "fieldValue");
-    }
-
-    private Map<String, Object> createObjectWithPrimitiveTypes(boolean includeType,
-            boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithPrimitiveTypes");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithPrimitiveTypes");
-        }
-        map.put("stringField", "stringValue");
-        map.put("integerObjectField", new Integer(1));
-        map.put("floatObjectField", new Float(2.5f));
-        map.put("doubleObjectField", new Double(3.5f));
-        map.put("integerField", 4);
-        map.put("floatField", 5.5f);
-        map.put("doubleField", 6.5d);
-        return map;
-    }
-
-    private void assertObjectWithPrimitiveTypes(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithPrimitiveTypes.class);
-        ObjectWithPrimitiveTypes casted = (ObjectWithPrimitiveTypes) object;
-        Assert.assertEquals(casted.stringField, "stringValue");
-        Assert.assertEquals(casted.integerObjectField, new Integer(1));
-        Assert.assertEquals(casted.floatObjectField, new Float(2.5f));
-        Assert.assertEquals(casted.doubleObjectField, new Double(3.5f));
-        Assert.assertEquals(casted.integerField, 4);
-        Assert.assertEquals(casted.floatField, 5.5f);
-        Assert.assertEquals(casted.doubleField, 6.5d);
-    }
-
-    private Map<String, Object> createObjectWithDateTypes(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithDateTypes");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithDateTypes");
-        }
-
-        long DAY_IN_MILLIS = 24 * 3600 * 1000;
-
-        map.put("utilDate", new java.util.Date(DAY_IN_MILLIS));
-        map.put("sqlDate", new java.sql.Date(DAY_IN_MILLIS * 2));
-        map.put("sqlTimestamp", new java.sql.Timestamp(DAY_IN_MILLIS * 3));
-        return map;
-    }
-
-    private void assertObjectWithDateTypes(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithDateTypes.class);
-        ObjectWithDateTypes casted = (ObjectWithDateTypes) object;
-
-        long DAY_IN_MILLIS = 24 * 3600 * 1000;
-
-        Assert.assertEquals(casted.utilDate.getTime(), new java.util.Date(DAY_IN_MILLIS).getTime());
-        Assert.assertEquals(casted.sqlDate.getTime(),
-                new java.sql.Date(DAY_IN_MILLIS * 2).getTime());
-        Assert.assertEquals(casted.sqlTimestamp.getTime(),
-                new java.sql.Timestamp(DAY_IN_MILLIS * 3).getTime());
-    }
-
-    private Map<String, Object> createObjectWithEnumTypes(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithEnumTypes");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithEnumTypes");
-        }
-        EnumSet<NestedEnum> enumSet = EnumSet.of(NestedEnum.VALUE1, NestedEnum.VALUE3);
-        EnumMap<NestedEnum, Object> enumMap =
-                new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2,
-                        "value2"));
-
-        map.put("enumField", "VALUE1");
-        map.put("enumSet", enumSet);
-        map.put("enumMap", enumMap);
-        return map;
-    }
-
-    private void assertObjectWithEnumTypes(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithEnumTypes.class);
-        ObjectWithEnumTypes casted = (ObjectWithEnumTypes) object;
-        Assert.assertEquals(casted.enumField, NestedEnum.VALUE1);
-
-        EnumSet<NestedEnum> enumSet = EnumSet.of(NestedEnum.VALUE1, NestedEnum.VALUE3);
-        EnumMap<NestedEnum, Object> enumMap =
-                new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2,
-                        "value2"));
-
-        Assert.assertEquals(casted.enumSet, enumSet);
-        Assert.assertEquals(casted.enumMap, enumMap);
-    }
-
-    private Map<String, Object> createObjectWithNestedTypes(boolean includeType,
-            boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectWithNestedTypes");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectWithNestedTypes");
-        }
-        Map<String, Object> nested = new HashMap<String, Object>();
-        nested.put("@type", "ObjectNested");
-        nested.put("nested", "nestedValue");
-
-        Map<String, Object> nestedChild = new HashMap<String, Object>();
-        nestedChild.put("@type", "ObjectNestedChild");
-        nestedChild.put("nested", "nestedValue");
-        nestedChild.put("nestedChild", "nestedChildValue");
-
-        map.put("propertyNested", nestedChild);
-        map.put("propertyNestedChild", nestedChild);
-        return map;
-    }
-
-    private void assertObjectWithNestedTypes(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectWithNestedTypes.class);
-        ObjectWithNestedTypes casted = (ObjectWithNestedTypes) object;
-
-        ObjectNestedChild propertyNested = (ObjectNestedChild) casted.propertyNested;
-        Assert.assertEquals("nestedValue", propertyNested.nested);
-        Assert.assertEquals("nestedChildValue", propertyNested.nestedChild);
-
-        ObjectNestedChild propertyNestedChild = casted.propertyNestedChild;
-        Assert.assertEquals("nestedValue", propertyNestedChild.nested);
-        Assert.assertEquals("nestedChildValue", propertyNestedChild.nestedChild);
-    }
-
-    private Map<String, Object> createObjectNested(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectNested");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectNested");
-        }
-        map.put("nested", "nestedValue");
-        return map;
-    }
-
-    private void assertObjectNested(Object object)
-    {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectNested.class);
-        ObjectNested casted = (ObjectNested) object;
-        Assert.assertEquals(casted.nested, "nestedValue");
-    }
-
-    private Map<String, Object> createObjectNestedChild(boolean includeType, boolean includeClass)
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        if (includeType)
-        {
-            map.put("@type", "ObjectNestedChild");
-        }
-        if (includeClass)
-        {
-            map.put("@class", ".LegacyObjectNestedChild");
-        }
-        map.put("nested", "nestedValue");
-        map.put("nestedChild", "nestedChildValue");
-        return map;
-    }
-
-    private void assertObjectNestedChild(Object object)
+    private void testDeserializeObjectWithIgnoredProperties(ObjectType includeType)
+            throws Exception
     {
-        Assert.assertNotNull(object);
-        Assert.assertEquals(object.getClass(), ObjectNestedChild.class);
-        ObjectNestedChild casted = (ObjectNestedChild) object;
-        Assert.assertEquals(casted.nested, "nestedValue");
-        Assert.assertEquals(casted.nestedChild, "nestedChildValue");
-    }
+        ObjectWithIgnoredProperties object =
+                ObjectWithIgnoredProperties.createObjectWithIgnoredPropertiesNull();
+        ObjectMap map = ObjectWithIgnoredProperties.createMap(null, includeType);
 
-    private Map<String, Object> createObjectWithKnownType()
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("@type", "ObjectWithTypeA");
-        map.put("base", "objectWithKnownType_base");
-        map.put("a", "objectWithKnownType_a");
-        return map;
+        Object result = deserialize(map.toMap(), ObjectWithIgnoredProperties.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void assertObjectWithKnownType(Object object)
+    private void testDeserializeObjectWithRenamedProperties(ObjectType includeType)
+            throws Exception
     {
-        Assert.assertEquals(object.getClass(), ObjectWithTypeA.class);
-        ObjectWithTypeA casted = (ObjectWithTypeA) object;
-        Assert.assertEquals("objectWithKnownType_base", casted.base);
-        Assert.assertEquals("objectWithKnownType_a", casted.a);
-    }
+        ObjectWithRenamedProperties object = ObjectWithRenamedProperties.createObject();
+        ObjectMap map = ObjectWithRenamedProperties.createMap(null, includeType);
 
-    private Map<String, Object> createObjectWithKnownUniqueClass()
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("@class", ".LegacyObjectWithTypeAA");
-        map.put("base", "objectWithKnownUniqueClass_base");
-        map.put("a", "objectWithKnownUniqueClass_a");
-        map.put("aa", "objectWithKnownUniqueClass_aa");
-        return map;
+        Object result = deserialize(map.toMap(), ObjectWithRenamedProperties.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void assertObjectWithKnownUniqueClass(Object object)
+    private void testDeserializeObjectWithPrivateAccess(ObjectType includeType) throws Exception
     {
-        Assert.assertEquals(object.getClass(), ObjectWithTypeAA.class);
-        ObjectWithTypeAA casted = (ObjectWithTypeAA) object;
-        Assert.assertEquals("objectWithKnownUniqueClass_base", casted.base);
-        Assert.assertEquals("objectWithKnownUniqueClass_a", casted.a);
-        Assert.assertEquals("objectWithKnownUniqueClass_aa", casted.aa);
-    }
+        ObjectWithPrivateAccess object = ObjectWithPrivateAccess.createObject();
+        ObjectMap map = ObjectWithPrivateAccess.createMap(null, includeType);
 
-    private Map<String, Object> createObjectWithKnownButNotUniqueClass()
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("@class", ".LegacyObjectWithTypeA");
-        map.put("base", "objectWithKnownButNotUniqueClass_base");
-        map.put("a", "objectWithKnownButNotUniqueClass_a");
-        return map;
+        Object result = deserialize(map.toMap(), ObjectWithPrivateAccess.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    @SuppressWarnings(
-        { "rawtypes", "unchecked" })
-    private void assertObjectWithKnownButNotUniqueClass(Object object)
+    private void testDeserializeObjectWithPrimitiveTypes(ObjectType includeType) throws Exception
     {
-        Assert.assertTrue(object instanceof Map);
-        Assert.assertEquals(new HashMap((Map) object), createObjectWithKnownButNotUniqueClass());
-    }
+        ObjectWithPrimitiveTypes object = ObjectWithPrimitiveTypes.createObject();
+        ObjectMap map = ObjectWithPrimitiveTypes.createMap(null, includeType);
 
-    private Map<String, Object> createObjectWithUnknownType()
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("@type", "ObjectWithTypeUnknown");
-        map.put("base", "objectWithUnknownType_base");
-        map.put("a", "objectWithUnknownType_a");
-        return map;
+        Object result = deserialize(map.toMap(), ObjectWithPrimitiveTypes.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    @SuppressWarnings(
-        { "rawtypes", "unchecked" })
-    private void assertObjectWithUnknownType(Object object)
+    private void testDeserializeObjectWithEnumTypes(ObjectType includeType) throws Exception
     {
-        Assert.assertTrue(object instanceof Map);
-        Assert.assertEquals(new HashMap((Map) object), createObjectWithUnknownType());
-    }
+        ObjectWithEnumTypes object = ObjectWithEnumTypes.createObject();
+        ObjectMap map = ObjectWithEnumTypes.createMap(null, includeType);
 
-    private Map<String, Object> createObjectWithUnknownClass()
-    {
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("@class", ".LegacyObjectWithTypeUnknown");
-        map.put("base", "objectWithUnknownClass_base");
-        map.put("a", "objectWithUnknownClass_a");
-        return map;
+        Object result = deserialize(map.toMap(), ObjectWithEnumTypes.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    @SuppressWarnings(
-        { "rawtypes", "unchecked" })
-    private void assertObjectWithUnknownClass(Object object)
+    private void testDeserializeObjectWithDateTypes(ObjectType includeType) throws Exception
     {
-        Assert.assertTrue(object instanceof Map);
-        Assert.assertEquals(new HashMap((Map) object), createObjectWithUnknownClass());
-    }
+        ObjectWithDateTypes object = ObjectWithDateTypes.createObject();
+        ObjectMap map = ObjectWithDateTypes.createMap(null, includeType);
 
-    @SuppressWarnings(
-        { "rawtypes", "unchecked" })
-    private Map<String, Object> createObjectWithContainerTypes(boolean includeType,
-            boolean includeClass)
-    {
-        Map map = new LinkedHashMap();
-        map.put("itemWithKnownType", createObjectWithKnownType());
-        map.put("itemWithKnownUniqueClass", createObjectWithKnownUniqueClass());
-        map.put("itemWithKnownButNotUniqueClass", createObjectWithKnownButNotUniqueClass());
-        map.put("itemWithUnknownType", createObjectWithUnknownType());
-        map.put("itemWithUnknownClass", createObjectWithUnknownClass());
-        map.put("itemWithPrivateAccess", createObjectWithPrivateAccess(includeType, includeClass));
-        map.put("itemWithPrimitiveTypes", createObjectWithPrimitiveTypes(includeType, includeClass));
-        map.put("itemWithNestedTypes", createObjectWithNestedTypes(includeType, includeClass));
-        map.put("itemWithEnumTypes", createObjectWithEnumTypes(includeType, includeClass));
-        map.put("itemWithDateTypes", createObjectWithDateTypes(includeType, includeClass));
-        map.put("itemWithIgnoredProperties",
-                createObjectWithIgnoredProperties(includeType, includeClass));
-        map.put("itemWithRenamedProperties",
-                createObjectWithRenamedProperties(includeType, includeClass));
-
-        Collection collection = new ArrayList(map.values());
-        List list = new ArrayList(map.values());
-        Object[] array = map.values().toArray(new Object[map.size()]);
-
-        Map specificMap = new LinkedHashMap();
-        specificMap.put("itemWithKnownType", createObjectWithKnownType());
-        specificMap.put("itemWithKnownUniqueClass", createObjectWithKnownUniqueClass());
-
-        Collection specificCollection = new ArrayList(specificMap.values());
-        List specificList = new ArrayList(specificMap.values());
-        Object[] specificArray = specificMap.values().toArray(new Object[specificMap.size()]);
-
-        Map<String, Object> object = new HashMap<String, Object>();
-
-        object.put("@type", "ObjectWithContainerTypes");
-        object.put("collectionWithoutType", collection);
-        object.put("collectionWithObjectType", collection);
-        object.put("collectionWithSpecificType", specificCollection);
-
-        object.put("linkedHashSetWithoutType", collection);
-        object.put("linkedHashSetWithObjectType", collection);
-        object.put("linkedHashSetWithSpecificType", specificCollection);
-
-        object.put("mapWithoutType", map);
-        object.put("mapWithObjectType", map);
-        object.put("mapWithSpecificType", specificMap);
-
-        object.put("linkedHashMapWithoutType", map);
-        object.put("linkedHashMapWithObjectType", map);
-        object.put("linkedHashMapWithSpecificType", specificMap);
-
-        object.put("listWithoutType", list);
-        object.put("listWithObjectType", list);
-        object.put("listWithSpecificType", specificList);
-
-        object.put("linkedListWithoutType", list);
-        object.put("linkedListWithObjectType", list);
-        object.put("linkedListWithSpecificType", specificList);
-
-        object.put("arrayWithObjectType", array);
-        object.put("arrayWithSpecificType", specificArray);
-
-        return object;
+        Object result = deserialize(map.toMap(), ObjectWithDateTypes.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void assertObjectWithContainerTypes(Object object)
+    private void testDeserializeObjectWithContainerTypes(ObjectType includeType) throws Exception
     {
-        Assert.assertEquals(object.getClass(), ObjectWithContainerTypes.class);
-        ObjectWithContainerTypes objectWithContainers = (ObjectWithContainerTypes) object;
-
-        assertObjectsCollection(objectWithContainers.collectionWithObjectType);
-        assertObjectsCollection(objectWithContainers.collectionWithoutType);
-        assertObjectsSpecificCollection(objectWithContainers.collectionWithSpecificType);
-
-        assertObjectsCollection(objectWithContainers.linkedHashSetWithObjectType);
-        assertObjectsCollection(objectWithContainers.linkedHashSetWithoutType);
-        assertObjectsSpecificCollection(objectWithContainers.linkedHashSetWithSpecificType);
+        ObjectWithContainerTypes object =
+                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
+        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
 
-        assertObjectsMap(objectWithContainers.mapWithObjectType);
-        assertObjectsMap(objectWithContainers.mapWithoutType);
-        assertObjectsSpecificMap(objectWithContainers.mapWithSpecificType);
-
-        assertObjectsMap(objectWithContainers.linkedHashMapWithObjectType);
-        assertObjectsMap(objectWithContainers.linkedHashMapWithoutType);
-        assertObjectsSpecificMap(objectWithContainers.linkedHashMapWithSpecificType);
-
-        assertObjectsCollection(objectWithContainers.listWithObjectType);
-        assertObjectsCollection(objectWithContainers.listWithoutType);
-        assertObjectsSpecificCollection(objectWithContainers.listWithSpecificType);
-
-        assertObjectsCollection(objectWithContainers.linkedListWithObjectType);
-        assertObjectsCollection(objectWithContainers.linkedListWithoutType);
-        assertObjectsSpecificCollection(objectWithContainers.linkedListWithSpecificType);
-
-        assertObjectsArray(objectWithContainers.arrayWithObjectType);
-        assertObjectsSpecificArray(objectWithContainers.arrayWithSpecificType);
+        Object result = deserialize(map.toMap(), ObjectWithContainerTypes.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    @SuppressWarnings(
-        { "rawtypes" })
-    private void assertObjectsCollection(Collection collection)
+    private void testDeserializeObjectWithNestedTypes(ObjectType includeType) throws Exception
     {
-        Assert.assertEquals(collection.size(), 12);
-        Iterator iterator = collection.iterator();
-        assertObjectWithKnownType(iterator.next());
-        assertObjectWithKnownUniqueClass(iterator.next());
-        assertObjectWithKnownButNotUniqueClass(iterator.next());
-        assertObjectWithUnknownType(iterator.next());
-        assertObjectWithUnknownClass(iterator.next());
-        assertObjectWithPrivateAccess(iterator.next());
-        assertObjectWithPrimitiveTypes(iterator.next());
-        assertObjectWithNestedTypes(iterator.next());
-        assertObjectWithEnumTypes(iterator.next());
-        assertObjectWithDateTypes(iterator.next());
-        assertObjectWithIgnoredProperties(iterator.next());
-        assertObjectWithRenamedProperties(iterator.next());
-    }
+        ObjectWithNestedTypes object = ObjectWithNestedTypes.createObject();
+        ObjectMap map = ObjectWithNestedTypes.createMap(null, includeType);
 
-    @SuppressWarnings(
-        { "rawtypes" })
-    private void assertObjectsSpecificCollection(Collection collection)
-    {
-        Assert.assertEquals(collection.size(), 2);
-        Iterator iterator = collection.iterator();
-        assertObjectWithKnownType(iterator.next());
-        assertObjectWithKnownUniqueClass(iterator.next());
+        Object result = deserialize(map.toMap(), ObjectWithNestedTypes.class);
+        Assert.assertTrue(object.equals(result));
     }
 
-    @SuppressWarnings(
-        { "rawtypes" })
-    private void assertObjectsMap(Map map)
+    private void testDeserializeObjectNested(ObjectType includeType, Class<?> rootClass)
+            throws Exception
     {
-        Assert.assertEquals(map.size(), 12);
-        assertObjectWithKnownType(map.get("itemWithKnownType"));
-        assertObjectWithKnownUniqueClass(map.get("itemWithKnownUniqueClass"));
-        assertObjectWithKnownButNotUniqueClass(map.get("itemWithKnownButNotUniqueClass"));
-        assertObjectWithUnknownType(map.get("itemWithUnknownType"));
-        assertObjectWithUnknownClass(map.get("itemWithUnknownClass"));
-        assertObjectWithPrivateAccess(map.get("itemWithPrivateAccess"));
-        assertObjectWithPrimitiveTypes(map.get("itemWithPrimitiveTypes"));
-        assertObjectWithNestedTypes(map.get("itemWithNestedTypes"));
-        assertObjectWithEnumTypes(map.get("itemWithEnumTypes"));
-        assertObjectWithDateTypes(map.get("itemWithDateTypes"));
-        assertObjectWithIgnoredProperties(map.get("itemWithIgnoredProperties"));
-        assertObjectWithRenamedProperties(map.get("itemWithRenamedProperties"));
-    }
+        ObjectNested object = ObjectNested.createObject();
+        ObjectMap map = ObjectNested.createMap(null, includeType);
 
-    @SuppressWarnings(
-        { "rawtypes" })
-    private void assertObjectsSpecificMap(Map map)
-    {
-        Assert.assertEquals(map.size(), 2);
-        assertObjectWithKnownType(map.get("itemWithKnownType"));
-        assertObjectWithKnownUniqueClass(map.get("itemWithKnownUniqueClass"));
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
-    private void assertObjectsArray(Object[] array)
+    private void testDeserializeObjectNestedChild(ObjectType includeType, Class<?> rootClass)
+            throws Exception
     {
-        assertObjectsCollection(Arrays.asList(array));
-    }
+        ObjectNestedChild object = ObjectNestedChild.createObject();
+        ObjectMap map = ObjectNestedChild.createMap(null, includeType);
 
-    private void assertObjectsSpecificArray(Object[] array)
-    {
-        assertObjectsSpecificCollection(Arrays.asList(array));
+        Object result = deserialize(map.toMap(), rootClass);
+        Assert.assertTrue(object.equals(result));
     }
 
     @SuppressWarnings("unchecked")
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java
index 909a4288e15..f183be0a2fa 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java
@@ -16,10 +16,6 @@
 
 package ch.systemsx.cisd.common.api.server.json;
 
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.EnumSet;
-import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.testng.Assert;
@@ -27,8 +23,10 @@ import org.testng.annotations.Test;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes.NestedEnum;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild;
@@ -47,404 +45,84 @@ public class JsonSerializationTest
     @Test
     public void testSerializeRootType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeValues(values, false);
-
-        ObjectWithType object = new ObjectWithType();
-        setObjectWithTypeFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
-    }
-
-    @Test
-    public void testSerializeRootTypeEmpty() throws Exception
-    {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeValues(values, true);
-
-        ObjectWithType object = new ObjectWithType();
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithType object = ObjectWithType.createObject();
+        ObjectMap map = ObjectWithType.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeFirstLevelSubType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeAValues(values, false);
-
-        ObjectWithTypeA object = new ObjectWithTypeA();
-        setObjectWithTypeAFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
-    }
-
-    @Test
-    public void testSerializeFirstLevelSubTypeEmpty() throws Exception
-    {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeAValues(values, true);
-
-        ObjectWithTypeA object = new ObjectWithTypeA();
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithTypeA object = ObjectWithTypeA.createObject();
+        ObjectMap map = ObjectWithTypeA.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeSecondLevelSubType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeAAValues(values, false);
-
-        ObjectWithTypeAA object = new ObjectWithTypeAA();
-        setObjectWithTypeAAFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
-    }
-
-    @Test
-    public void testSerializeSecondLevelSubTypeEmpty() throws Exception
-    {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeAAValues(values, true);
-
-        ObjectWithTypeAA object = new ObjectWithTypeAA();
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithTypeAA object = ObjectWithTypeAA.createObject();
+        ObjectMap map = ObjectWithTypeAA.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeNestedRootType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeNestedValues(values, false);
-
-        ObjectNested object = new ObjectNested();
-        setObjectWithTypeNestedFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
-    }
-
-    @Test
-    public void testSerializeNestedRootTypeEmpty() throws Exception
-    {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeNestedValues(values, true);
-
-        ObjectNested object = new ObjectNested();
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectNested object = ObjectNested.createObject();
+        ObjectMap map = ObjectNested.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeNestedSubType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeNestedChildValues(values, false);
-
-        ObjectNestedChild object = new ObjectNestedChild();
-        setObjectWithTypeNestedChildFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
-    }
-
-    @Test
-    public void testSerializeNestedSubTypeEmpty() throws Exception
-    {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeNestedChildValues(values, true);
-
-        ObjectNestedChild object = new ObjectNestedChild();
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectNestedChild object = ObjectNestedChild.createObject();
+        ObjectMap map = ObjectNestedChild.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializePolymorphicType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeValues(values, false);
-
-        ObjectWithType object = new ObjectWithType();
-        setObjectWithTypeFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithType object = ObjectWithType.createObject();
+        ObjectMap map = ObjectWithType.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeNotPolymorphicType() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithTypeButNoSubtypesValues(values, false);
-
-        ObjectWithTypeButNoSubtypes object = new ObjectWithTypeButNoSubtypes();
-        setObjectWithTypeButNoSubtypesFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithTypeButNoSubtypes object = ObjectWithTypeButNoSubtypes.createObject();
+        ObjectMap map = ObjectWithTypeButNoSubtypes.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeObjectWithPrimitiveTypes() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithPrimitiveTypesValues(values, false);
-
-        ObjectWithPrimitiveTypes object = new ObjectWithPrimitiveTypes();
-        setObjectWithPrimitiveTypesFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithPrimitiveTypes object = ObjectWithPrimitiveTypes.createObject();
+        ObjectMap map = ObjectWithPrimitiveTypes.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeObjectWithNestedTypes() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithNestedTypesValues(values, false);
-
-        ObjectWithNestedTypes object = new ObjectWithNestedTypes();
-        setObjectWithNestedTypesFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
+        ObjectWithNestedTypes object = ObjectWithNestedTypes.createObject();
+        ObjectMap map = ObjectWithNestedTypes.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
     @Test
     public void testSerializeObjectWithEnumTypes() throws Exception
     {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        putObjectWithEnumTypesValues(values, false);
-
-        ObjectWithEnumTypes object = new ObjectWithEnumTypes();
-        setObjectWithEnumTypesFields(object);
-
-        serializeObjectAndCheckItsValues(object, values);
-    }
-
-    private void putObjectWithTypeValues(Map<String, Object> map, boolean empty)
-    {
-        map.put("@type", "ObjectWithType");
-
-        if (empty)
-        {
-            map.put("base", null);
-        } else
-        {
-            map.put("base", "baseValue");
-        }
-    }
-
-    private void setObjectWithTypeFields(ObjectWithType object)
-    {
-        object.base = "baseValue";
-    }
-
-    private void putObjectWithTypeAValues(Map<String, Object> map, boolean empty)
-    {
-        putObjectWithTypeValues(map, empty);
-        map.put("@type", "ObjectWithTypeA");
-
-        if (empty)
-        {
-            map.put("a", null);
-        } else
-        {
-            map.put("a", "aValue");
-        }
-    }
-
-    private void setObjectWithTypeAFields(ObjectWithTypeA object)
-    {
-        setObjectWithTypeFields(object);
-        object.a = "aValue";
-    }
-
-    private void putObjectWithTypeAAValues(Map<String, Object> map, boolean empty)
-    {
-        putObjectWithTypeAValues(map, empty);
-        map.put("@type", "ObjectWithTypeAA");
-
-        if (empty)
-        {
-            map.put("aa", null);
-        } else
-        {
-            map.put("aa", "aaValue");
-        }
-    }
-
-    private void setObjectWithTypeAAFields(ObjectWithTypeAA object)
-    {
-        setObjectWithTypeAFields(object);
-        object.aa = "aaValue";
-    }
-
-    private void putObjectWithTypeNestedValues(Map<String, Object> map, boolean empty)
-    {
-        map.put("@type", "ObjectNested");
-
-        if (empty)
-        {
-            map.put("nested", null);
-        } else
-        {
-            map.put("nested", "nestedValue");
-        }
-
-    }
-
-    private void setObjectWithTypeNestedFields(ObjectNested object)
-    {
-        object.nested = "nestedValue";
-    }
-
-    private void putObjectWithTypeNestedChildValues(Map<String, Object> map, boolean empty)
-    {
-        putObjectWithTypeNestedValues(map, empty);
-        map.put("@type", "ObjectNestedChild");
-
-        if (empty)
-        {
-            map.put("nestedChild", null);
-        } else
-        {
-            map.put("nestedChild", "nestedChildValue");
-        }
-    }
-
-    private void setObjectWithTypeNestedChildFields(ObjectNestedChild object)
-    {
-        setObjectWithTypeNestedFields(object);
-        object.nestedChild = "nestedChildValue";
-    }
-
-    private void putObjectWithTypeButNoSubtypesValues(Map<String, Object> map, boolean empty)
-    {
-        map.put("@type", "ObjectWithTypeButNoSubtypes");
-
-        if (empty)
-        {
-            map.put("a", null);
-            map.put("b", null);
-        } else
-        {
-            map.put("a", "aValue");
-            map.put("b", "bValue");
-        }
-    }
-
-    private void setObjectWithTypeButNoSubtypesFields(ObjectWithTypeButNoSubtypes object)
-    {
-        object.a = "aValue";
-        object.b = "bValue";
-    }
-
-    private void putObjectWithPrimitiveTypesValues(Map<String, Object> map, boolean empty)
-    {
-        map.put("@type", "ObjectWithPrimitiveTypes");
-
-        if (empty)
-        {
-            map.put("stringField", null);
-            map.put("integerObjectField", null);
-            map.put("floatObjectField", null);
-            map.put("doubleObjectField", null);
-            map.put("integerField", null);
-            map.put("floatField", null);
-            map.put("doubleField", null);
-        } else
-        {
-            map.put("stringField", "stringValue");
-            map.put("integerObjectField", new Integer(1));
-            map.put("floatObjectField", new Float(2.5f));
-            map.put("doubleObjectField", new Double(3.5f));
-            map.put("integerField", 4);
-            map.put("floatField", 5.5f);
-            map.put("doubleField", 6.5d);
-        }
-    }
-
-    private void setObjectWithPrimitiveTypesFields(ObjectWithPrimitiveTypes object)
-    {
-        object.stringField = "stringValue";
-        object.integerObjectField = new Integer(1);
-        object.floatObjectField = new Float(2.5f);
-        object.doubleObjectField = new Double(3.5f);
-        object.integerField = 4;
-        object.floatField = 5.5f;
-        object.doubleField = 6.5d;
-    }
-
-    private void putObjectWithNestedTypesValues(Map<String, Object> map, boolean empty)
-    {
-        map.put("@type", "ObjectWithNestedTypes");
-
-        if (empty)
-        {
-            map.put("propertyNested", null);
-            map.put("propertyNestedChild", null);
-        } else
-        {
-            Map<String, Object> nested = new LinkedHashMap<String, Object>();
-            nested.put("@type", "ObjectNested");
-            nested.put("nested", "nestedValue");
-
-            Map<String, Object> nestedChild = new LinkedHashMap<String, Object>();
-            nestedChild.put("@type", "ObjectNestedChild");
-            nestedChild.put("nested", "nestedValue");
-            nestedChild.put("nestedChild", "nestedChildValue");
-
-            map.put("propertyNested", nestedChild);
-            map.put("propertyNestedChild", nestedChild);
-        }
-    }
-
-    private void setObjectWithNestedTypesFields(ObjectWithNestedTypes object)
-    {
-        ObjectNested nested = new ObjectNested();
-        nested.nested = "nestedValue";
-
-        ObjectNestedChild nestedChild = new ObjectNestedChild();
-        nestedChild.nested = "nestedValue";
-        nestedChild.nestedChild = "nestedChildValue";
-
-        object.propertyNested = nestedChild;
-        object.propertyNestedChild = nestedChild;
-    }
-
-    private void putObjectWithEnumTypesValues(Map<String, Object> map, boolean empty)
-    {
-        map.put("@type", "ObjectWithEnumTypes");
-
-        if (empty)
-        {
-            map.put("enumField", null);
-            map.put("enumSet", null);
-            map.put("enumMap", null);
-        } else
-        {
-            EnumSet<NestedEnum> enumSet = EnumSet.of(NestedEnum.VALUE1, NestedEnum.VALUE3);
-            EnumMap<NestedEnum, Object> enumMap =
-                    new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2,
-                            "value2"));
-
-            map.put("enumField", "VALUE1");
-            map.put("enumSet", enumSet);
-            map.put("enumMap", enumMap);
-        }
-    }
-
-    private void setObjectWithEnumTypesFields(ObjectWithEnumTypes object)
-    {
-        EnumSet<NestedEnum> enumSet = EnumSet.of(NestedEnum.VALUE1, NestedEnum.VALUE3);
-        EnumMap<NestedEnum, Object> enumMap =
-                new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2,
-                        "value2"));
-
-        object.enumField = NestedEnum.VALUE1;
-        object.enumSet = enumSet;
-        object.enumMap = enumMap;
+        ObjectWithEnumTypes object = ObjectWithEnumTypes.createObject();
+        ObjectMap map = ObjectWithEnumTypes.createMap(new ObjectCounter(), ObjectType.TYPE);
+        serializeObjectAndMapAndCompare(object, map.toMap());
     }
 
-    private void serializeObjectAndCheckItsValues(Object object, Map<String, Object> expectedMap)
+    private void serializeObjectAndMapAndCompare(Object object, Map<String, Object> expectedMap)
             throws Exception
     {
         String jsonFromObject = new JsonTestObjectMapper().writeValueAsString(object);
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java
index e1a41e6aae8..1b445d15a16 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.common.api.server.json;
 
+import com.fasterxml.jackson.databind.MapperFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext;
 
@@ -58,32 +59,30 @@ public class JsonTestObjectMapper extends ObjectMapper
         setAnnotationIntrospector(new JsonTypeAndClassAnnotationIntrospector(getClassMapping()));
         setSubtypeResolver(new JsonReflectionsSubTypeResolver(getTypeMapping()));
         setSerializerFactory(new JsonSerializerFactory());
+        configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
     }
 
     private static IJsonClassValueToClassObjectsMapping getClassMapping()
     {
         JsonStaticClassValueToClassObjectsMapping classMapping =
                 new JsonStaticClassValueToClassObjectsMapping();
-        classMapping.addClass(".LegacyObjectWithType", ObjectWithType.class);
-        classMapping.addClass(".LegacyObjectWithTypeA", ObjectWithTypeA.class);
-        classMapping.addClass(".LegacyObjectWithTypeA", ObjectWithTypeALegalDuplicate.class);
-        classMapping.addClass(".LegacyObjectWithTypeAA", ObjectWithTypeAA.class);
-        classMapping.addClass(".LegacyObjectWithTypeB", ObjectWithTypeB.class);
-        classMapping.addClass(".LegacyObjectWithTypeB", ObjectWithTypeBIllegalDuplicate.class);
-        classMapping.addClass(".LegacyObjectWithTypeButNoSubtypes",
-                ObjectWithTypeButNoSubtypes.class);
-        classMapping.addClass(".LegacyObjectNested", ObjectNested.class);
-        classMapping.addClass(".LegacyObjectNestedChild", ObjectNestedChild.class);
-        classMapping.addClass(".LegacyObjectWithPrimitiveTypes", ObjectWithPrimitiveTypes.class);
-        classMapping.addClass(".LegacyObjectWithNestedTypes", ObjectWithNestedTypes.class);
-        classMapping.addClass(".LegacyObjectWithEnumTypes", ObjectWithEnumTypes.class);
-        classMapping.addClass(".LegacyObjectWithContainerTypes", ObjectWithContainerTypes.class);
-        classMapping.addClass(".LegacyObjectWithDateTypes", ObjectWithDateTypes.class);
-        classMapping.addClass(".LegacyObjectWithIgnoredProperties",
-                ObjectWithIgnoredProperties.class);
-        classMapping.addClass(".LegacyObjectWithRenamedProperties",
-                ObjectWithRenamedProperties.class);
-        classMapping.addClass(".LegacyObjectWithPrivateAccess", ObjectWithPrivateAccess.class);
+        classMapping.addClass(ObjectWithType.CLASS, ObjectWithType.class);
+        classMapping.addClass(ObjectWithTypeA.CLASS, ObjectWithTypeA.class);
+        classMapping.addClass(ObjectWithTypeA.CLASS, ObjectWithTypeALegalDuplicate.class);
+        classMapping.addClass(ObjectWithTypeAA.CLASS, ObjectWithTypeAA.class);
+        classMapping.addClass(ObjectWithTypeB.CLASS, ObjectWithTypeB.class);
+        classMapping.addClass(ObjectWithTypeB.CLASS, ObjectWithTypeBIllegalDuplicate.class);
+        classMapping.addClass(ObjectWithTypeButNoSubtypes.CLASS, ObjectWithTypeButNoSubtypes.class);
+        classMapping.addClass(ObjectNested.CLASS, ObjectNested.class);
+        classMapping.addClass(ObjectNestedChild.CLASS, ObjectNestedChild.class);
+        classMapping.addClass(ObjectWithPrimitiveTypes.CLASS, ObjectWithPrimitiveTypes.class);
+        classMapping.addClass(ObjectWithNestedTypes.CLASS, ObjectWithNestedTypes.class);
+        classMapping.addClass(ObjectWithEnumTypes.CLASS, ObjectWithEnumTypes.class);
+        classMapping.addClass(ObjectWithContainerTypes.CLASS, ObjectWithContainerTypes.class);
+        classMapping.addClass(ObjectWithDateTypes.CLASS, ObjectWithDateTypes.class);
+        classMapping.addClass(ObjectWithIgnoredProperties.CLASS, ObjectWithIgnoredProperties.class);
+        classMapping.addClass(ObjectWithRenamedProperties.CLASS, ObjectWithRenamedProperties.class);
+        classMapping.addClass(ObjectWithPrivateAccess.CLASS, ObjectWithPrivateAccess.class);
         return classMapping;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectCounter.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectCounter.java
new file mode 100644
index 00000000000..127784d66a3
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectCounter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.api.server.json.common;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectCounter
+{
+
+    private int counter;
+
+    public ObjectCounter()
+    {
+        this.counter = 1;
+    }
+
+    public int current()
+    {
+        return counter;
+    }
+
+    public int next()
+    {
+        return counter++;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java
new file mode 100644
index 00000000000..8b901e6c7d1
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.api.server.json.common;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author pkupczyk
+ */
+@SuppressWarnings("hiding")
+public class ObjectMap
+{
+
+    private Integer objectId;
+
+    private ObjectType objectType;
+
+    private String type;
+
+    private String clazz;
+
+    private Map<String, Object> fields = new TreeMap<String, Object>();
+
+    public void putId(ObjectCounter objectCounter)
+    {
+        if (objectCounter != null)
+        {
+            this.objectId = objectCounter.next();
+        }
+    }
+
+    public void putType(String type, String clazz, ObjectType objectType)
+    {
+        this.type = type;
+        this.clazz = clazz;
+        this.objectType = objectType;
+    }
+
+    public void putField(String name, Object value)
+    {
+        fields.put(name, value);
+    }
+
+    public Map<String, Object> toMap()
+    {
+        Map<String, Object> map = new LinkedHashMap<String, Object>();
+
+        if (ObjectType.TYPE.equals(objectType) || ObjectType.TYPE_AND_CLASS.equals(objectType))
+        {
+            map.put("@type", type);
+        }
+        if (ObjectType.CLASS.equals(objectType) || ObjectType.TYPE_AND_CLASS.equals(objectType))
+        {
+            map.put("@class", clazz);
+        }
+        if (objectId != null)
+        {
+            map.put("@id", objectId);
+        }
+
+        map.putAll(fields);
+        return map;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java
new file mode 100644
index 00000000000..b5f2aaa33a1
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.api.server.json.common;
+
+/**
+ * @author pkupczyk
+ */
+public enum ObjectType
+{
+
+    NONE, TYPE, CLASS, TYPE_AND_CLASS
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java
index 76dcd06977c..93f5e852a17 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java
@@ -16,23 +16,100 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
 @SuppressWarnings("rawtypes")
-@JsonObject("ObjectWithContainerTypes")
+@JsonObject(ObjectWithContainerTypes.TYPE)
 public class ObjectWithContainerTypes
 {
 
+    public static final String TYPE = "ObjectWithContainerTypes";
+
+    public static final String CLASS = ".LegacyObjectWithContainerTypes";
+
+    public static final String COLLECTION_WITHOUT_TYPE = "collectionWithoutType";
+
+    public static final String COLLECTION_WITH_OBJECT_TYPE = "collectionWithObjectType";
+
+    public static final String COLLECTION_WITH_SPECIFIC_TYPE = "collectionWithSpecificType";
+
+    public static final String LINKED_HASH_SET_WITHOUT_TYPE = "linkedHashSetWithoutType";
+
+    public static final String LINKED_HASH_SET_WITH_OBJECT_TYPE = "linkedHashSetWithObjectType";
+
+    public static final String LINKED_HASH_SET_WITH_SPECIFIC_TYPE = "linkedHashSetWithSpecificType";
+
+    public static final String LIST_WITHOUT_TYPE = "listWithoutType";
+
+    public static final String LIST_WITH_OBJECT_TYPE = "listWithObjectType";
+
+    public static final String LIST_WITH_SPECIFIC_TYPE = "listWithSpecificType";
+
+    public static final String LINKED_LIST_WITHOUT_TYPE = "linkedListWithoutType";
+
+    public static final String LINKED_LIST_WITH_OBJECT_TYPE = "linkedListWithObjectType";
+
+    public static final String LINKED_LIST_WITH_SPECIFIC_TYPE = "linkedListWithSpecificType";
+
+    public static final String MAP_WITHOUT_TYPE = "mapWithoutType";
+
+    public static final String MAP_WITH_OBJECT_TYPE = "mapWithObjectType";
+
+    public static final String MAP_WITH_SPECIFIC_TYPE = "mapWithSpecificType";
+
+    public static final String LINKED_HASH_MAP_WITHOUT_TYPE = "linkedHashMapWithoutType";
+
+    public static final String LINKED_HASH_MAP_WITH_OBJECT_TYPE = "linkedHashMapWithObjectType";
+
+    public static final String LINKED_HASH_MAP_WITH_SPECIFIC_TYPE = "linkedHashMapWithSpecificType";
+
+    public static final String ARRAY_WITH_OBJECT_TYPE = "arrayWithObjectType";
+
+    public static final String ARRAY_WITH_SPECIFIC_TYPE = "arrayWithSpecificType";
+
+    public static final String ITEM_WITH_KNOWN_TYPE = "itemWithKnownType";
+
+    public static final String ITEM_WITH_KNOWN_UNIQUE_CLASS = "itemWithKnownUniqueClass";
+
+    public static final String ITEM_WITH_RENAMED_PROPERTIES = "itemWithRenamedProperties";
+
+    public static final String ITEM_WITH_IGNORED_PROPERTIES = "itemWithIgnoredProperties";
+
+    public static final String ITEM_WITH_DATE_TYPES = "itemWithDateTypes";
+
+    public static final String ITEM_WITH_ENUM_TYPES = "itemWithEnumTypes";
+
+    public static final String ITEM_WITH_NESTED_TYPES = "itemWithNestedTypes";
+
+    public static final String ITEM_WITH_PRIMITIVE_TYPES = "itemWithPrimitiveTypes";
+
+    public static final String ITEM_WITH_PRIVATE_ACCESS = "itemWithPrivateAccess";
+
+    public static final String ITEM_WITH_UNKNOWN_CLASS = "itemWithUnknownClass";
+
+    public static final String ITEM_WITH_UNKNOWN_TYPE = "itemWithUnknownType";
+
+    public static final String ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS =
+            "itemWithKnownButNotUniqueClass";
+
     public Collection collectionWithoutType;
 
     public Collection<Object> collectionWithObjectType;
@@ -41,9 +118,9 @@ public class ObjectWithContainerTypes
 
     public LinkedHashSet linkedHashSetWithoutType;
 
-    public Collection<Object> linkedHashSetWithObjectType;
+    public LinkedHashSet<Object> linkedHashSetWithObjectType;
 
-    public Collection<ObjectWithType> linkedHashSetWithSpecificType;
+    public LinkedHashSet<ObjectWithType> linkedHashSetWithSpecificType;
 
     public List listWithoutType;
 
@@ -63,14 +140,236 @@ public class ObjectWithContainerTypes
 
     public Map<String, ObjectWithType> mapWithSpecificType;
 
-    public Map linkedHashMapWithoutType;
+    public LinkedHashMap linkedHashMapWithoutType;
 
-    public Map<String, Object> linkedHashMapWithObjectType;
+    public LinkedHashMap<String, Object> linkedHashMapWithObjectType;
 
-    public Map<String, ObjectWithType> linkedHashMapWithSpecificType;
+    public LinkedHashMap<String, ObjectWithType> linkedHashMapWithSpecificType;
 
     public Object[] arrayWithObjectType;
 
     public ObjectWithType[] arrayWithSpecificType;
 
+    public static ObjectWithContainerTypes createObject()
+    {
+        LinkedHashMap map = createItemsObjectsMap();
+        LinkedHashMap specificMap = createItemsObjectsSpecificMap();
+        return createObjectCommon(map, specificMap);
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    public static ObjectWithContainerTypes createObjectWithIncorrectObjectsAsMaps()
+    {
+        LinkedHashMap map = createItemsObjectsMap();
+        map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
+                ObjectWithTypeA.createMap(null, ObjectType.CLASS).toMap());
+        map.put(ITEM_WITH_UNKNOWN_TYPE, ObjectWithUnknownType.createMap(null, ObjectType.TYPE)
+                .toMap());
+        map.put(ITEM_WITH_UNKNOWN_CLASS, ObjectWithUnknownType.createMap(null, ObjectType.CLASS)
+                .toMap());
+        LinkedHashMap specificMap = createItemsObjectsSpecificMap();
+        return createObjectCommon(map, specificMap);
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    private static ObjectWithContainerTypes createObjectCommon(Map aMap, Map aSpecificMap)
+    {
+        Map map = new HashMap(aMap);
+        LinkedHashMap linkedHashMap = new LinkedHashMap(aMap);
+        Collection collection = new ArrayList(aMap.values());
+        LinkedHashSet linkedHashSet = new LinkedHashSet(aMap.values());
+        List list = new ArrayList(aMap.values());
+        LinkedList linkedList = new LinkedList(aMap.values());
+        Object[] array = aMap.values().toArray(new Object[aMap.size()]);
+
+        Map specificMap = new HashMap(aSpecificMap);
+        LinkedHashMap specificLinkedHashMap = new LinkedHashMap(aSpecificMap);
+        Collection specificCollection = new ArrayList(aSpecificMap.values());
+        LinkedHashSet specificLinkedHashSet = new LinkedHashSet(aSpecificMap.values());
+        List specificList = new ArrayList(aSpecificMap.values());
+        LinkedList specificLinkedList = new LinkedList(aSpecificMap.values());
+        ObjectWithType[] specificArray =
+                (ObjectWithType[]) aSpecificMap.values().toArray(
+                        new ObjectWithType[aSpecificMap.size()]);
+
+        ObjectWithContainerTypes object = new ObjectWithContainerTypes();
+        object.collectionWithoutType = collection;
+        object.collectionWithObjectType = collection;
+        object.collectionWithSpecificType = specificCollection;
+        object.linkedHashSetWithoutType = linkedHashSet;
+        object.linkedHashSetWithObjectType = linkedHashSet;
+        object.linkedHashSetWithSpecificType = specificLinkedHashSet;
+        object.listWithoutType = list;
+        object.listWithObjectType = list;
+        object.listWithSpecificType = specificList;
+        object.linkedListWithoutType = linkedList;
+        object.linkedListWithObjectType = linkedList;
+        object.linkedListWithSpecificType = specificLinkedList;
+        object.mapWithoutType = map;
+        object.mapWithObjectType = map;
+        object.mapWithSpecificType = specificMap;
+        object.linkedHashMapWithoutType = linkedHashMap;
+        object.linkedHashMapWithObjectType = linkedHashMap;
+        object.linkedHashMapWithSpecificType = specificLinkedHashMap;
+        object.arrayWithObjectType = array;
+        object.arrayWithSpecificType = specificArray;
+        return object;
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        Map map = createItemsMapsMap(objectCounter, objectType);
+        Collection collection = new ArrayList(map.values());
+        List list = new ArrayList(map.values());
+        Object[] array = map.values().toArray(new Object[map.size()]);
+
+        Map specificMap = createItemsMapsSpecificMap(objectCounter, objectType);
+        Collection specificCollection = new ArrayList(specificMap.values());
+        List specificList = new ArrayList(specificMap.values());
+        Object[] specificArray = specificMap.values().toArray(new Object[specificMap.size()]);
+
+        ObjectMap object = new ObjectMap();
+        object.putId(objectCounter);
+        object.putType(TYPE, CLASS, objectType);
+        object.putField(COLLECTION_WITHOUT_TYPE, collection);
+        object.putField(COLLECTION_WITH_OBJECT_TYPE, collection);
+        object.putField(COLLECTION_WITH_SPECIFIC_TYPE, specificCollection);
+
+        object.putField(LINKED_HASH_SET_WITHOUT_TYPE, collection);
+        object.putField(LINKED_HASH_SET_WITH_OBJECT_TYPE, collection);
+        object.putField(LINKED_HASH_SET_WITH_SPECIFIC_TYPE, specificCollection);
+
+        object.putField(MAP_WITHOUT_TYPE, map);
+        object.putField(MAP_WITH_OBJECT_TYPE, map);
+        object.putField(MAP_WITH_SPECIFIC_TYPE, specificMap);
+
+        object.putField(LINKED_HASH_MAP_WITHOUT_TYPE, map);
+        object.putField(LINKED_HASH_MAP_WITH_OBJECT_TYPE, map);
+        object.putField(LINKED_HASH_MAP_WITH_SPECIFIC_TYPE, specificMap);
+
+        object.putField(LIST_WITHOUT_TYPE, list);
+        object.putField(LIST_WITH_OBJECT_TYPE, list);
+        object.putField(LIST_WITH_SPECIFIC_TYPE, specificList);
+
+        object.putField(LINKED_LIST_WITHOUT_TYPE, list);
+        object.putField(LINKED_LIST_WITH_OBJECT_TYPE, list);
+        object.putField(LINKED_LIST_WITH_SPECIFIC_TYPE, specificList);
+
+        object.putField(ARRAY_WITH_OBJECT_TYPE, array);
+        object.putField(ARRAY_WITH_SPECIFIC_TYPE, specificArray);
+
+        return object;
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    private static LinkedHashMap createItemsObjectsMap()
+    {
+        LinkedHashMap map = new LinkedHashMap();
+        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createObject());
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS, ObjectWithTypeAA.createObject());
+        map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS, ObjectWithTypeA.createObject());
+        map.put(ITEM_WITH_UNKNOWN_TYPE, ObjectWithUnknownType.createObject());
+        map.put(ITEM_WITH_UNKNOWN_CLASS, ObjectWithUnknownType.createObject());
+        map.put(ITEM_WITH_PRIVATE_ACCESS, ObjectWithPrivateAccess.createObject());
+        map.put(ITEM_WITH_PRIMITIVE_TYPES, ObjectWithPrimitiveTypes.createObject());
+        map.put(ITEM_WITH_NESTED_TYPES, ObjectWithNestedTypes.createObject());
+        map.put(ITEM_WITH_ENUM_TYPES, ObjectWithEnumTypes.createObject());
+        map.put(ITEM_WITH_DATE_TYPES, ObjectWithDateTypes.createObject());
+        map.put(ITEM_WITH_IGNORED_PROPERTIES,
+                ObjectWithIgnoredProperties.createObjectWithIgnoredPropertiesNull());
+        map.put(ITEM_WITH_RENAMED_PROPERTIES, ObjectWithRenamedProperties.createObject());
+        return map;
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    private static LinkedHashMap createItemsObjectsSpecificMap()
+    {
+        LinkedHashMap map = new LinkedHashMap();
+        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createObject());
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS, ObjectWithTypeAA.createObject());
+        return map;
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    private static LinkedHashMap createItemsMapsMap(ObjectCounter objectCounter,
+            ObjectType objectType)
+    {
+        LinkedHashMap map = new LinkedHashMap();
+        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createMap(objectCounter, ObjectType.TYPE)
+                .toMap());
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS,
+                ObjectWithTypeAA.createMap(objectCounter, ObjectType.CLASS).toMap());
+        map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
+                ObjectWithTypeA.createMap(objectCounter, ObjectType.CLASS).toMap());
+        map.put(ITEM_WITH_UNKNOWN_TYPE,
+                ObjectWithUnknownType.createMap(objectCounter, ObjectType.TYPE).toMap());
+        map.put(ITEM_WITH_UNKNOWN_CLASS,
+                ObjectWithUnknownType.createMap(objectCounter, ObjectType.CLASS).toMap());
+        map.put(ITEM_WITH_PRIVATE_ACCESS,
+                ObjectWithPrivateAccess.createMap(objectCounter, objectType).toMap());
+        map.put(ITEM_WITH_PRIMITIVE_TYPES,
+                ObjectWithPrimitiveTypes.createMap(objectCounter, objectType).toMap());
+        map.put(ITEM_WITH_NESTED_TYPES, ObjectWithNestedTypes.createMap(objectCounter, objectType)
+                .toMap());
+        map.put(ITEM_WITH_ENUM_TYPES, ObjectWithEnumTypes.createMap(objectCounter, objectType)
+                .toMap());
+        map.put(ITEM_WITH_DATE_TYPES, ObjectWithDateTypes.createMap(objectCounter, objectType)
+                .toMap());
+        map.put(ITEM_WITH_IGNORED_PROPERTIES,
+                ObjectWithIgnoredProperties.createMap(objectCounter, objectType).toMap());
+        map.put(ITEM_WITH_RENAMED_PROPERTIES,
+                ObjectWithRenamedProperties.createMap(objectCounter, objectType).toMap());
+        return map;
+    }
+
+    @SuppressWarnings(
+        { "unchecked" })
+    private static Map createItemsMapsSpecificMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        Map map = new LinkedHashMap();
+        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createMap(objectCounter, ObjectType.TYPE)
+                .toMap());
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS,
+                ObjectWithTypeAA.createMap(objectCounter, ObjectType.CLASS).toMap());
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithContainerTypes casted = (ObjectWithContainerTypes) obj;
+        Assert.assertEquals(collectionWithoutType, casted.collectionWithoutType);
+        Assert.assertEquals(collectionWithObjectType, casted.collectionWithObjectType);
+        Assert.assertEquals(collectionWithSpecificType, casted.collectionWithSpecificType);
+        Assert.assertEquals(linkedHashSetWithoutType, casted.linkedHashSetWithoutType);
+        Assert.assertEquals(linkedHashSetWithObjectType, casted.linkedHashSetWithObjectType);
+        Assert.assertEquals(linkedHashSetWithSpecificType, casted.linkedHashSetWithSpecificType);
+        Assert.assertEquals(listWithoutType, casted.listWithoutType);
+        Assert.assertEquals(listWithObjectType, casted.listWithObjectType);
+        Assert.assertEquals(listWithSpecificType, casted.listWithSpecificType);
+        Assert.assertEquals(linkedListWithoutType, casted.linkedListWithoutType);
+        Assert.assertEquals(linkedListWithObjectType, casted.linkedListWithObjectType);
+        Assert.assertEquals(linkedListWithSpecificType, casted.linkedListWithSpecificType);
+        Assert.assertEquals(mapWithoutType, casted.mapWithoutType);
+        Assert.assertEquals(mapWithObjectType, casted.mapWithObjectType);
+        Assert.assertEquals(mapWithSpecificType, casted.mapWithSpecificType);
+        Assert.assertEquals(linkedHashMapWithoutType, casted.linkedHashMapWithoutType);
+        Assert.assertEquals(linkedHashMapWithObjectType, casted.linkedHashMapWithObjectType);
+        Assert.assertEquals(linkedHashMapWithSpecificType, casted.linkedHashMapWithSpecificType);
+        Assert.assertEquals(arrayWithObjectType, casted.arrayWithObjectType);
+        Assert.assertEquals(arrayWithSpecificType, casted.arrayWithSpecificType);
+
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java
index 6835abc163d..9a5c7bcaffa 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java
@@ -16,20 +16,77 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
-@JsonObject("ObjectWithDateTypes")
+@JsonObject(ObjectWithDateTypes.TYPE)
 public class ObjectWithDateTypes
 {
 
+    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
+
+    public static final String TYPE = "ObjectWithDateTypes";
+
+    public static final String CLASS = ".LegacyObjectWithDateTypes";
+
+    public static final String UTIL_DATE = "utilDate";
+
+    public static final java.util.Date UTIL_DATE_VALUE = new java.util.Date(DAY_IN_MILLIS);
+
+    public static final String SQL_DATE = "sqlDate";
+
+    public static final java.sql.Date SQL_DATE_VALUE = new java.sql.Date(DAY_IN_MILLIS * 2);
+
+    public static final String SQL_TIMESTAMP = "sqlTimestamp";
+
+    public static final java.sql.Timestamp SQL_TIMESTAMP_VALUE = new java.sql.Timestamp(
+            DAY_IN_MILLIS * 3);
+
     public java.util.Date utilDate;
 
     public java.sql.Date sqlDate;
 
     public java.sql.Timestamp sqlTimestamp;
 
+    public static ObjectWithDateTypes createObject()
+    {
+        ObjectWithDateTypes object = new ObjectWithDateTypes();
+        object.utilDate = UTIL_DATE_VALUE;
+        object.sqlDate = SQL_DATE_VALUE;
+        object.sqlTimestamp = SQL_TIMESTAMP_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(UTIL_DATE, UTIL_DATE_VALUE);
+        map.putField(SQL_DATE, SQL_DATE_VALUE);
+        map.putField(SQL_TIMESTAMP, SQL_TIMESTAMP_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithDateTypes casted = (ObjectWithDateTypes) obj;
+        Assert.assertEquals(utilDate, casted.utilDate);
+        Assert.assertEquals(sqlDate, casted.sqlDate);
+        Assert.assertEquals(sqlTimestamp, casted.sqlTimestamp);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java
index 1c8287eef84..400cb4be478 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java
@@ -16,19 +16,43 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import java.util.Collections;
 import java.util.EnumMap;
 import java.util.EnumSet;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
-@JsonObject("ObjectWithEnumTypes")
+@JsonObject(ObjectWithEnumTypes.TYPE)
 public class ObjectWithEnumTypes
 {
 
+    public static final String TYPE = "ObjectWithEnumTypes";
+
+    public static final String CLASS = ".LegacyObjectWithEnumTypes";
+
+    public static final String ENUM_FIELD = "enumField";
+
+    public static final NestedEnum ENUM_FIELD_VALUE = NestedEnum.VALUE1;
+
+    public static final String ENUM_SET = "enumSet";
+
+    public static final EnumSet<NestedEnum> ENUM_SET_VALUE = EnumSet.of(NestedEnum.VALUE1,
+            NestedEnum.VALUE3);
+
+    public static final String ENUM_MAP = "enumMap";
+
+    public static final EnumMap<NestedEnum, Object> ENUM_MAP_VALUE =
+            new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2, "value2"));
+
     public NestedEnum enumField;
 
     public EnumSet<NestedEnum> enumSet;
@@ -41,4 +65,37 @@ public class ObjectWithEnumTypes
         VALUE1, VALUE2, VALUE3
     }
 
+    public static ObjectWithEnumTypes createObject()
+    {
+        ObjectWithEnumTypes object = new ObjectWithEnumTypes();
+        object.enumField = ENUM_FIELD_VALUE;
+        object.enumSet = ENUM_SET_VALUE;
+        object.enumMap = ENUM_MAP_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(ENUM_FIELD, ENUM_FIELD_VALUE);
+        map.putField(ENUM_SET, ENUM_SET_VALUE);
+        map.putField(ENUM_MAP, ENUM_MAP_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithEnumTypes casted = (ObjectWithEnumTypes) obj;
+        Assert.assertEquals(enumField, casted.enumField);
+        Assert.assertEquals(enumSet, casted.enumSet);
+        Assert.assertEquals(enumMap, casted.enumMap);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java
index f10e09f8d14..fc8a138b70d 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java
@@ -16,17 +16,45 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithIgnoredProperties")
+@JsonObject(ObjectWithIgnoredProperties.TYPE)
 public class ObjectWithIgnoredProperties
 {
 
+    public static final String TYPE = "ObjectWithIgnoredProperties";
+
+    public static final String CLASS = ".LegacyObjectWithIgnoredProperties";
+
+    public static final String PROPERTY = "property";
+
+    public static final String PROPERTY_VALUE = "propertyValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER = "propertyWithGetterAndSetter";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_VALUE =
+            "propertyWithGetterAndSetterValue";
+
+    public static final String PROPERTY_IGNORED = "propertyIgnored";
+
+    public static final String PROPERTY_IGNORED_VALUE = "propertyIgnoredValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_IGNORED =
+            "propertyWithGetterAndSetterIgnored";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE =
+            "propertyWithGetterAndSetterIgnoredValue";
+
     public String property;
 
     private String propertyWithGetterAndSetter;
@@ -57,4 +85,50 @@ public class ObjectWithIgnoredProperties
         return propertyWithGetterAndSetterIgnored;
     }
 
+    public static ObjectWithIgnoredProperties createObject()
+    {
+        ObjectWithIgnoredProperties object = new ObjectWithIgnoredProperties();
+        object.property = PROPERTY_VALUE;
+        object.propertyIgnored = PROPERTY_IGNORED_VALUE;
+        object.propertyWithGetterAndSetter = PROPERTY_WITH_GETTER_AND_SETTER_VALUE;
+        object.propertyWithGetterAndSetterIgnored = PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE;
+        return object;
+    }
+
+    public static ObjectWithIgnoredProperties createObjectWithIgnoredPropertiesNull()
+    {
+        ObjectWithIgnoredProperties object = new ObjectWithIgnoredProperties();
+        object.property = PROPERTY_VALUE;
+        object.propertyWithGetterAndSetter = PROPERTY_WITH_GETTER_AND_SETTER_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        map.putField(PROPERTY_IGNORED, PROPERTY_IGNORED_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER_IGNORED,
+                PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithIgnoredProperties casted = (ObjectWithIgnoredProperties) obj;
+        Assert.assertEquals(property, casted.property);
+        Assert.assertEquals(propertyIgnored, casted.propertyIgnored);
+        Assert.assertEquals(propertyWithGetterAndSetter, casted.propertyWithGetterAndSetter);
+        Assert.assertEquals(propertyWithGetterAndSetterIgnored,
+                casted.propertyWithGetterAndSetterIgnored);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java
index e4cc095550b..6a5ba7f4426 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java
@@ -16,15 +16,29 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithNestedTypes")
+@SuppressWarnings("hiding")
+@JsonObject(ObjectWithNestedTypes.TYPE)
 public class ObjectWithNestedTypes
 {
 
+    public static final String TYPE = "ObjectWithNestedTypes";
+
+    public static final String CLASS = ".LegacyObjectWithNestedTypes";
+
+    public static final String PROPERTY_NESTED = "propertyNested";
+
+    public static final String PROPERTY_NESTED_CHILD = "propertyNestedChild";
+
     // TODO: check why it doesn't work properly during both serialization and deserialization
     // public Object propertyObject;
 
@@ -32,16 +46,122 @@ public class ObjectWithNestedTypes
 
     public ObjectNestedChild propertyNestedChild;
 
-    @JsonObject("ObjectNested")
+    @JsonObject(ObjectNested.TYPE)
     public static class ObjectNested
     {
+        public static final String TYPE = "ObjectNested";
+
+        public static final String CLASS = ".LegacyObjectNested";
+
+        public static final String NESTED = "nested";
+
+        public static final String NESTED_VALUE = "nestedValue";
+
         public String nested;
+
+        public static ObjectNested createObject()
+        {
+            ObjectNested object = new ObjectNested();
+            object.nested = NESTED_VALUE;
+            return object;
+        }
+
+        public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+        {
+            ObjectMap map = new ObjectMap();
+            map.putId(objectCounter);
+            map.putType(TYPE, CLASS, objectType);
+            map.putField(NESTED, NESTED_VALUE);
+            return map;
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            Assert.assertNotNull(obj);
+            Assert.assertEquals(getClass(), obj.getClass());
+
+            ObjectNested casted = (ObjectNested) obj;
+            Assert.assertEquals(nested, casted.nested);
+            return true;
+        }
+
     }
 
-    @JsonObject("ObjectNestedChild")
+    @JsonObject(ObjectNestedChild.TYPE)
     public static class ObjectNestedChild extends ObjectNested
     {
+        public static final String TYPE = "ObjectNestedChild";
+
+        public static final String CLASS = ".LegacyObjectNestedChild";
+
+        public static final String NESTED_CHILD = "nestedChild";
+
+        public static final String NESTED_CHILD_VALUE = "nestedChildValue";
+
         public String nestedChild;
+
+        public static ObjectNestedChild createObject()
+        {
+            ObjectNestedChild object = new ObjectNestedChild();
+            object.nested = NESTED_VALUE;
+            object.nestedChild = NESTED_CHILD_VALUE;
+            return object;
+        }
+
+        public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+        {
+            ObjectMap map = new ObjectMap();
+            map.putId(objectCounter);
+            map.putType(TYPE, CLASS, objectType);
+            map.putField(NESTED, NESTED_VALUE);
+            map.putField(NESTED_CHILD, NESTED_CHILD_VALUE);
+            return map;
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            Assert.assertNotNull(obj);
+            Assert.assertEquals(getClass(), obj.getClass());
+
+            ObjectNestedChild casted = (ObjectNestedChild) obj;
+            Assert.assertEquals(nested, casted.nested);
+            Assert.assertEquals(nestedChild, casted.nestedChild);
+            return true;
+        }
+
+    }
+
+    public static ObjectWithNestedTypes createObject()
+    {
+        ObjectWithNestedTypes object = new ObjectWithNestedTypes();
+        object.propertyNested = ObjectNested.createObject();
+        object.propertyNestedChild = ObjectNestedChild.createObject();
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY_NESTED, ObjectNested.createMap(objectCounter, objectType).toMap());
+        map.putField(PROPERTY_NESTED_CHILD, ObjectNestedChild.createMap(objectCounter, objectType)
+                .toMap());
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithNestedTypes casted = (ObjectWithNestedTypes) obj;
+        Assert.assertEquals(propertyNested, casted.propertyNested);
+        Assert.assertEquals(propertyNestedChild, casted.propertyNestedChild);
+        return true;
     }
 
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java
index 9f092badb63..b5cf25f051f 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java
@@ -16,15 +16,52 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithPrimitiveTypes")
+@JsonObject(ObjectWithPrimitiveTypes.TYPE)
 public class ObjectWithPrimitiveTypes
 {
 
+    public static final String TYPE = "ObjectWithPrimitiveTypes";
+
+    public static final String CLASS = ".LegacyObjectWithPrimitiveTypes";
+
+    public static final String STRING_FIELD = "stringField";
+
+    public static final String STRING_FIELD_VALUE = "stringValue";
+
+    public static final String INTEGER_OBJECT_FIELD = "integerObjectField";
+
+    public static final Integer INTEGER_OBJECT_FIELD_VALUE = new Integer(1);
+
+    public static final String FLOAT_OBJECT_FIELD = "floatObjectField";
+
+    public static final Float FLOAT_OBJECT_FIELD_VALUE = new Float(2.5f);
+
+    public static final String DOUBLE_OBJECT_FIELD = "doubleObjectField";
+
+    public static final Double DOUBLE_OBJECT_FIELD_VALUE = new Double(3.5d);
+
+    public static final String INTEGER_FIELD = "integerField";
+
+    public static final int INTEGER_FIELD_VALUE = 4;
+
+    public static final String FLOAT_FIELD = "floatField";
+
+    public static final float FLOAT_FIELD_VALUE = 5.5f;
+
+    public static final String DOUBLE_FIELD = "doubleField";
+
+    public static final double DOUBLE_FIELD_VALUE = 6.5d;
+
     public String stringField;
 
     public Integer integerObjectField;
@@ -39,4 +76,48 @@ public class ObjectWithPrimitiveTypes
 
     public double doubleField;
 
+    public static ObjectWithPrimitiveTypes createObject()
+    {
+        ObjectWithPrimitiveTypes object = new ObjectWithPrimitiveTypes();
+        object.stringField = STRING_FIELD_VALUE;
+        object.integerObjectField = INTEGER_OBJECT_FIELD_VALUE;
+        object.floatObjectField = FLOAT_OBJECT_FIELD_VALUE;
+        object.doubleObjectField = DOUBLE_OBJECT_FIELD_VALUE;
+        object.integerField = INTEGER_FIELD_VALUE;
+        object.floatField = FLOAT_FIELD_VALUE;
+        object.doubleField = DOUBLE_FIELD_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(STRING_FIELD, STRING_FIELD_VALUE);
+        map.putField(INTEGER_OBJECT_FIELD, INTEGER_OBJECT_FIELD_VALUE);
+        map.putField(FLOAT_OBJECT_FIELD, FLOAT_OBJECT_FIELD_VALUE);
+        map.putField(DOUBLE_OBJECT_FIELD, DOUBLE_OBJECT_FIELD_VALUE);
+        map.putField(INTEGER_FIELD, INTEGER_FIELD_VALUE);
+        map.putField(FLOAT_FIELD, FLOAT_FIELD_VALUE);
+        map.putField(DOUBLE_FIELD, DOUBLE_FIELD_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithPrimitiveTypes casted = (ObjectWithPrimitiveTypes) obj;
+        Assert.assertEquals(stringField, casted.stringField);
+        Assert.assertEquals(integerObjectField, casted.integerObjectField);
+        Assert.assertEquals(floatObjectField, casted.floatObjectField);
+        Assert.assertEquals(doubleObjectField, casted.doubleObjectField);
+        Assert.assertEquals(integerField, casted.integerField);
+        Assert.assertEquals(floatField, casted.floatField);
+        Assert.assertEquals(doubleField, casted.doubleField);
+        return true;
+    }
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java
index 6eaad338c61..ccb660c3539 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java
@@ -16,16 +16,29 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
-@JsonObject("ObjectWithPrivateAccess")
+@JsonObject(ObjectWithPrivateAccess.TYPE)
 public class ObjectWithPrivateAccess
 {
 
+    public static final String TYPE = "ObjectWithPrivateAccess";
+
+    public static final String CLASS = ".LegacyObjectWithPrivateAccess";
+
+    public static final String FIELD = "field";
+
+    public static final String FIELD_VALUE = "fieldValue";
+
     private String field;
 
     private ObjectWithPrivateAccess()
@@ -43,4 +56,31 @@ public class ObjectWithPrivateAccess
         this.field = field;
     }
 
+    public static ObjectWithPrivateAccess createObject()
+    {
+        ObjectWithPrivateAccess object = new ObjectWithPrivateAccess();
+        object.field = FIELD_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField("field", "fieldValue");
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithPrivateAccess casted = (ObjectWithPrivateAccess) obj;
+        Assert.assertEquals(field, casted.field);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java
index 863baae6de3..ad85cacd96c 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java
@@ -16,17 +16,45 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithRenamedProperties")
+@JsonObject(ObjectWithRenamedProperties.TYPE)
 public class ObjectWithRenamedProperties
 {
 
+    public static final String TYPE = "ObjectWithRenamedProperties";
+
+    public static final String CLASS = ".LegacyObjectWithRenamedProperties";
+
+    public static final String PROPERTY = "property";
+
+    public static final String PROPERTY_VALUE = "propertyValue";
+
+    public static final String PROPERTY_RENAMED = "propertyRenamed";
+
+    public static final String PROPERTY_RENAMED_VALUE = "propertyRenamedValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER = "propertyWithGetterAndSetter";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_VALUE =
+            "propertyWithGetterAndSetterValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_RENAMED =
+            "propertyWithGetterAndSetterRenamed";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE =
+            "propertyWithGetterAndSetterRenamedValue";
+
     public String property;
 
     private String propertyWithGetterAndSetter;
@@ -57,4 +85,41 @@ public class ObjectWithRenamedProperties
         this.y = y;
     }
 
+    public static ObjectWithRenamedProperties createObject()
+    {
+        ObjectWithRenamedProperties object = new ObjectWithRenamedProperties();
+        object.property = PROPERTY_VALUE;
+        object.x = PROPERTY_RENAMED_VALUE;
+        object.propertyWithGetterAndSetter = PROPERTY_WITH_GETTER_AND_SETTER_VALUE;
+        object.y = PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        map.putField(PROPERTY_RENAMED, PROPERTY_RENAMED_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER_RENAMED,
+                PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithRenamedProperties casted = (ObjectWithRenamedProperties) obj;
+        Assert.assertEquals(property, casted.property);
+        Assert.assertEquals(x, casted.x);
+        Assert.assertEquals(propertyWithGetterAndSetter, casted.propertyWithGetterAndSetter);
+        Assert.assertEquals(y, casted.y);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java
index 4e2ad540e69..144b1403b66 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java
@@ -1,6 +1,11 @@
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /*
  * Copyright 2012 ETH Zuerich, CISD
@@ -21,10 +26,45 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithType")
+@JsonObject(ObjectWithType.TYPE)
 public class ObjectWithType implements ObjectWithTypeInterface1, ObjectWithTypeInterface2
 {
 
+    public static final String TYPE = "ObjectWithType";
+
+    public static final String CLASS = ".LegacyObjectWithType";
+
+    public static final String BASE = "base";
+
+    public static final String BASE_VALUE = "baseValue";
+
     public String base;
 
+    public static ObjectWithType createObject()
+    {
+        ObjectWithType object = new ObjectWithType();
+        object.base = BASE_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithType casted = (ObjectWithType) obj;
+        Assert.assertEquals(base, casted.base);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java
index a596bd4e73b..b34ff07f263 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java
@@ -1,6 +1,11 @@
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /*
  * Copyright 2012 ETH Zuerich, CISD
@@ -21,10 +26,49 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithTypeA")
+@SuppressWarnings("hiding")
+@JsonObject(ObjectWithTypeA.TYPE)
 public class ObjectWithTypeA extends ObjectWithType
 {
 
+    public static final String TYPE = "ObjectWithTypeA";
+
+    public static final String CLASS = ".LegacyObjectWithTypeA";
+
+    public static final String A = "a";
+
+    public static final String A_VALUE = "aValue";
+
     public String a;
 
+    public static ObjectWithTypeA createObject()
+    {
+        ObjectWithTypeA object = new ObjectWithTypeA();
+        object.base = BASE_VALUE;
+        object.a = A_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithTypeA casted = (ObjectWithTypeA) obj;
+        Assert.assertEquals(base, casted.base);
+        Assert.assertEquals(a, casted.a);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java
index cd9fb7f7da8..a4caaaacd86 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java
@@ -16,15 +16,62 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithTypeAA")
+@SuppressWarnings("hiding")
+@JsonObject(ObjectWithTypeAA.TYPE)
 public class ObjectWithTypeAA extends ObjectWithTypeA
 {
 
+    public static final String TYPE = "ObjectWithTypeAA";
+
+    public static final String CLASS = ".LegacyObjectWithTypeAA";
+
+    public static final String AA = "aa";
+
+    public static final String AA_VALUE = "aaValue";
+
     public String aa;
 
+    public static ObjectWithTypeAA createObject()
+    {
+        ObjectWithTypeAA object = new ObjectWithTypeAA();
+        object.base = BASE_VALUE;
+        object.a = A_VALUE;
+        object.aa = AA_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        map.putField(AA, AA_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithTypeAA casted = (ObjectWithTypeAA) obj;
+        Assert.assertEquals(base, casted.base);
+        Assert.assertEquals(a, casted.a);
+        Assert.assertEquals(aa, casted.aa);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java
index 29a582964b9..91673372366 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java
@@ -1,6 +1,5 @@
 package ch.systemsx.cisd.common.api.server.json.object;
 
-
 import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.common.api.server.json.JsonUniqueCheckIgnore;
 
@@ -24,7 +23,7 @@ import ch.systemsx.cisd.common.api.server.json.JsonUniqueCheckIgnore;
  * @author pkupczyk
  */
 @JsonUniqueCheckIgnore
-@JsonObject("ObjectWithTypeA")
+@JsonObject(ObjectWithTypeA.TYPE)
 public class ObjectWithTypeALegalDuplicate
 {
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java
index 1e615e39ce8..3d62dfab4d1 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java
@@ -1,6 +1,11 @@
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /*
  * Copyright 2012 ETH Zuerich, CISD
@@ -21,10 +26,49 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithTypeB")
+@SuppressWarnings("hiding")
+@JsonObject(ObjectWithTypeB.TYPE)
 public class ObjectWithTypeB extends ObjectWithType
 {
 
+    public static final String TYPE = "ObjectWithTypeB";
+
+    public static final String CLASS = ".LegacyObjectWithTypeB";
+
+    public static final String B = "b";
+
+    public static final String B_VALUE = "bValue";
+
     public String b;
 
+    public static ObjectWithTypeB createObject()
+    {
+        ObjectWithTypeB object = new ObjectWithTypeB();
+        object.base = BASE_VALUE;
+        object.b = B_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(B, B_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithTypeB casted = (ObjectWithTypeB) obj;
+        Assert.assertEquals(base, casted.base);
+        Assert.assertEquals(b, casted.b);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java
index 9b4a467760e..21dd7b2df2b 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java
@@ -1,6 +1,5 @@
 package ch.systemsx.cisd.common.api.server.json.object;
 
-
 import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.common.api.server.json.JsonUniqueCheckIgnore;
 
@@ -23,7 +22,7 @@ import ch.systemsx.cisd.common.api.server.json.JsonUniqueCheckIgnore;
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithTypeB")
+@JsonObject(ObjectWithTypeB.TYPE)
 @JsonUniqueCheckIgnore
 public class ObjectWithTypeBIllegalDuplicate extends ObjectWithType
 {
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java
index 646f82c3bb2..9ff64fb8699 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java
@@ -16,17 +16,64 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithTypeButNoSubtypes")
+@JsonObject(ObjectWithTypeButNoSubtypes.TYPE)
 public class ObjectWithTypeButNoSubtypes
 {
 
+    public static final String TYPE = "ObjectWithTypeButNoSubtypes";
+
+    public static final String CLASS = ".LegacyObjectWithTypeButNoSubtypes";
+
+    public static final String A = "a";
+
+    public static final String A_VALUE = "aValue";
+
+    public static final String B = "b";
+
+    public static final String B_VALUE = "bValue";
+
     public String a;
 
     public String b;
 
+    public static ObjectWithTypeButNoSubtypes createObject()
+    {
+        ObjectWithTypeButNoSubtypes object = new ObjectWithTypeButNoSubtypes();
+        object.a = A_VALUE;
+        object.b = B_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField("a", "aValue");
+        map.putField("b", "bValue");
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithTypeButNoSubtypes casted = (ObjectWithTypeButNoSubtypes) obj;
+        Assert.assertEquals(a, casted.a);
+        Assert.assertEquals(b, casted.b);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java
index 1e49a12c4fb..a0064f0e1d6 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java
@@ -16,15 +16,59 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
+import org.testng.Assert;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject("ObjectWithTypeC")
+@SuppressWarnings("hiding")
+@JsonObject(ObjectWithTypeC.TYPE)
 public class ObjectWithTypeC extends ObjectWithType
 {
 
+    public static final String TYPE = "ObjectWithTypeC";
+
+    public static final String CLASS = ".LegacyObjectWithTypeC";
+
+    public static final String C = "c";
+
+    public static final String C_VALUE = "cValue";
+
     public String c;
 
+    public static ObjectWithTypeC createObject()
+    {
+        ObjectWithTypeC object = new ObjectWithTypeC();
+        object.base = BASE_VALUE;
+        object.c = C_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(C, C_VALUE);
+        return map;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(getClass(), obj.getClass());
+
+        ObjectWithTypeC casted = (ObjectWithTypeC) obj;
+        Assert.assertEquals(base, casted.base);
+        Assert.assertEquals(c, casted.c);
+        return true;
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java
new file mode 100644
index 00000000000..4a99a6d4b89
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.api.server.json.object;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithUnknownType
+{
+
+    public static final String TYPE = "ObjectWithUnknownType";
+
+    public static final String CLASS = ".LegacyObjectWithUnknownType";
+
+    public static final String PROPERTY = "property";
+
+    public static final String PROPERTY_VALUE = "propertyValue";
+
+    public String property;
+
+    public static ObjectWithUnknownType createObject()
+    {
+        ObjectWithUnknownType object = new ObjectWithUnknownType();
+        object.property = PROPERTY_VALUE;
+        return object;
+    }
+
+    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        return map;
+    }
+
+}
-- 
GitLab