You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ra...@apache.org on 2018/07/09 08:42:15 UTC

olingo-odata4 git commit: [OLINGO-1273]The V4 client responses should be as per values of odata.metadata parameter

Repository: olingo-odata4
Updated Branches:
  refs/heads/master 1fef3a131 -> 2696359f3


[OLINGO-1273]The V4 client responses should be as per values of odata.metadata parameter


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/2696359f
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/2696359f
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/2696359f

Branch: refs/heads/master
Commit: 2696359f33fe132f9ced6cc5ee1a4c619c020786
Parents: 1fef3a1
Author: ramya vasanth <ra...@sap.com>
Authored: Mon Jul 9 14:12:03 2018 +0530
Committer: ramya vasanth <ra...@sap.com>
Committed: Mon Jul 9 14:12:03 2018 +0530

----------------------------------------------------------------------
 .../base/BoundOperationInvokeTestITCase.java    |   1 +
 .../serialization/JsonEntitySerializer.java     |  39 +-
 .../serialization/JsonEntitySetSerializer.java  |   8 +-
 .../serialization/JsonPropertySerializer.java   |   4 +-
 .../core/serialization/JsonSerializer.java      |  28 +-
 .../org/apache/olingo/client/core/AtomTest.java |   3 +-
 .../org/apache/olingo/client/core/JSONTest.java | 463 +++++++++++++++++--
 .../client/core/CustomersWithFullMetadata.json  |  75 +++
 .../client/core/Customers_InServerMode.json     | 135 ++++++
 .../Employees_3_HomeAddress_InServerMode.json   |  13 +
 .../client/core/Products_5_InServerMode.json    | 104 +++++
 .../client/core/Products_5_SkinColor_Null.json  |   5 +
 .../core/Products_5_SkinColor_NullType.json     |   5 +
 .../Products_5_SkinColor_PrimitiveType.json     |   5 +
 .../core/collectionOfEntityReferences.json      |   1 +
 15 files changed, 826 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
index ecd15c7..f1bd078 100644
--- a/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
@@ -403,6 +403,7 @@ public class BoundOperationInvokeTestITCase extends AbstractTestITCase {
             new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Product"),
             false,
             Collections.<String, ClientValue> singletonMap("accessRight", accessRight));
+    getProductDetailsReq.setFormat(ContentType.JSON_FULL_METADATA);
     final ClientProperty getProductDetailsRes = getProductDetailsReq.execute().getBody();
     assertNotNull(getProductDetailsRes);
     assertTrue(getProductDetailsRes.hasEnumValue());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySerializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySerializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySerializer.java
index 6b49012..07e8952 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySerializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySerializer.java
@@ -55,7 +55,7 @@ public class JsonEntitySerializer extends JsonSerializer {
 
     jgen.writeStartObject();
 
-    if (serverMode) {
+    if (serverMode && !isODataMetadataNone) {
       if (container.getContextURL() != null) {
         jgen.writeStringField(Constants.JSON_CONTEXT, container.getContextURL().toASCIIString());
       }
@@ -68,12 +68,12 @@ public class JsonEntitySerializer extends JsonSerializer {
       }
     }
 
-    if (entity.getType() != null && !isODataMetadataNone) {
+    if (entity.getType() != null && isODataMetadataFull) {
       jgen.writeStringField(Constants.JSON_TYPE,
           new EdmTypeInfo.Builder().setTypeExpression(entity.getType()).build().external());
     }
 
-    if (entity.getId() != null && !isODataMetadataNone) {
+    if (entity.getId() != null && isODataMetadataFull) {
       jgen.writeStringField(Constants.JSON_ID, entity.getId().toASCIIString());
     }
 
@@ -85,10 +85,11 @@ public class JsonEntitySerializer extends JsonSerializer {
       valuable(jgen, property, property.getName());
     }
 
-    if (serverMode && entity.getEditLink() != null && entity.getEditLink().getHref() != null) {
+    if (serverMode && entity.getEditLink() != null && 
+        entity.getEditLink().getHref() != null && isODataMetadataFull) {
       jgen.writeStringField(Constants.JSON_EDIT_LINK, entity.getEditLink().getHref());
 
-      if (entity.isMediaEntity()) {
+      if (entity.isMediaEntity() && isODataMetadataFull) {
         jgen.writeStringField(Constants.JSON_MEDIA_READ_LINK,
             entity.getEditLink().getHref() + "/$value");
       }
@@ -98,24 +99,26 @@ public class JsonEntitySerializer extends JsonSerializer {
       links(entity, jgen);
     }
 
-    for (Link link : entity.getMediaEditLinks()) {
-      if (link.getTitle() == null) {
-        jgen.writeStringField(Constants.JSON_MEDIA_EDIT_LINK, link.getHref());
-      }
+    if (isODataMetadataFull) {
+      for (Link link : entity.getMediaEditLinks()) {
+        if (link.getTitle() == null) {
+          jgen.writeStringField(Constants.JSON_MEDIA_EDIT_LINK, link.getHref());
+        }
 
-      if (link.getInlineEntity() != null) {
-        jgen.writeObjectField(link.getTitle(), link.getInlineEntity());
-      }
-      if (link.getInlineEntitySet() != null) {
-        jgen.writeArrayFieldStart(link.getTitle());
-        for (Entity subEntry : link.getInlineEntitySet().getEntities()) {
-          jgen.writeObject(subEntry);
+        if (link.getInlineEntity() != null) {
+          jgen.writeObjectField(link.getTitle(), link.getInlineEntity());
+        }
+        if (link.getInlineEntitySet() != null) {
+          jgen.writeArrayFieldStart(link.getTitle());
+          for (Entity subEntry : link.getInlineEntitySet().getEntities()) {
+            jgen.writeObject(subEntry);
+          }
+          jgen.writeEndArray();
         }
-        jgen.writeEndArray();
       }
     }
 
-    if (serverMode) {
+    if (serverMode && isODataMetadataFull) {
       for (Operation operation : entity.getOperations()) {
         final String anchor = operation.getMetadataAnchor();
         final int index = anchor.lastIndexOf('#');

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetSerializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetSerializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetSerializer.java
index fceafe8..d648664 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetSerializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonEntitySetSerializer.java
@@ -40,7 +40,7 @@ public class JsonEntitySetSerializer extends JsonSerializer {
       throws IOException, EdmPrimitiveTypeException {
     doContainerSerialize(new ResWrap<EntityCollection>(null, null, entitySet), jgen);
   }
-
+  
   protected void doContainerSerialize(final ResWrap<EntityCollection> container, final JsonGenerator jgen)
       throws IOException, EdmPrimitiveTypeException {
 
@@ -48,7 +48,7 @@ public class JsonEntitySetSerializer extends JsonSerializer {
 
     jgen.writeStartObject();
 
-    if (serverMode) {
+    if (serverMode && !isODataMetadataNone) {
       if (container.getContextURL() != null) {
         jgen.writeStringField(Constants.JSON_CONTEXT, container.getContextURL().toASCIIString());
       }
@@ -58,7 +58,7 @@ public class JsonEntitySetSerializer extends JsonSerializer {
       }
     }
 
-    if (entitySet.getId() != null) {
+    if (entitySet.getId() != null && isODataMetadataFull) {
       jgen.writeStringField(Constants.JSON_ID, entitySet.getId().toASCIIString());
     }
     final Integer count = entitySet.getCount() == null ? entitySet.getEntities().size() : entitySet.getCount();
@@ -72,7 +72,7 @@ public class JsonEntitySetSerializer extends JsonSerializer {
         jgen.writeStringField(Constants.JSON_NEXT_LINK,
             entitySet.getNext().toASCIIString());
       }
-      if (entitySet.getDeltaLink() != null) {
+      if (entitySet.getDeltaLink() != null && !isODataMetadataNone) {
         jgen.writeStringField(Constants.JSON_DELTA_LINK,
             entitySet.getDeltaLink().toASCIIString());
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertySerializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertySerializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertySerializer.java
index 7db45f9..2ada791 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertySerializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonPropertySerializer.java
@@ -53,11 +53,11 @@ public class JsonPropertySerializer extends JsonSerializer {
 
     jgen.writeStartObject();
 
-    if (serverMode && container.getContextURL() != null) {
+    if (serverMode && container.getContextURL() != null && !isODataMetadataNone) {
       jgen.writeStringField(Constants.JSON_CONTEXT, container.getContextURL().toASCIIString());
     }
 
-    if (StringUtils.isNotBlank(property.getType())) {
+    if (StringUtils.isNotBlank(property.getType()) && isODataMetadataFull) {
       jgen.writeStringField(Constants.JSON_TYPE,
           new EdmTypeInfo.Builder().setTypeExpression(property.getType()).build().external());
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonSerializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonSerializer.java
index d7198d9..57931eb 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonSerializer.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/JsonSerializer.java
@@ -65,12 +65,14 @@ public class JsonSerializer implements ODataSerializer {
   protected ContentType contentType;
   protected final boolean isIEEE754Compatible;
   protected final boolean isODataMetadataNone;
+  protected final boolean isODataMetadataFull;
 
   public JsonSerializer(final boolean serverMode, final ContentType contentType) {
     this.serverMode = serverMode;
     this.contentType = contentType;
     this.isIEEE754Compatible = isIEEE754Compatible();
     this.isODataMetadataNone = isODataMetadataNone();
+    this.isODataMetadataFull = isODataMetadataFull();
   }
 
   @Override
@@ -97,7 +99,9 @@ public class JsonSerializer implements ODataSerializer {
   private void reference(final ResWrap<URI> container, final JsonGenerator json) throws IOException {
     json.writeStartObject();
 
-    json.writeStringField(Constants.JSON_CONTEXT, container.getContextURL().toASCIIString());
+    if (!isODataMetadataNone) {
+      json.writeStringField(Constants.JSON_CONTEXT, container.getContextURL().toASCIIString());
+    }
     json.writeStringField(Constants.JSON_ID, container.getPayload().toASCIIString());
 
     json.writeEndObject();
@@ -200,7 +204,7 @@ public class JsonSerializer implements ODataSerializer {
 
   protected void serverLinks(final Linked linked, final JsonGenerator jgen)
       throws IOException, EdmPrimitiveTypeException {
-    if (linked instanceof Entity) {
+    if (linked instanceof Entity && isODataMetadataFull) {
       for (Link link : ((Entity) linked).getMediaEditLinks()) {
         if (link.getHref() != null && !link.getHref().isEmpty()) {
           jgen.writeStringField(link.getTitle() + Constants.JSON_MEDIA_EDIT_LINK, link.getHref());
@@ -208,9 +212,11 @@ public class JsonSerializer implements ODataSerializer {
       }
     }
 
-    for (Link link : linked.getAssociationLinks()) {
-      if (link.getHref() != null && !link.getHref().isEmpty()) {
-        jgen.writeStringField(link.getTitle() + Constants.JSON_ASSOCIATION_LINK, link.getHref());
+    if (isODataMetadataFull) {
+      for (Link link : linked.getAssociationLinks()) {
+        if (link.getHref() != null && !link.getHref().isEmpty()) {
+          jgen.writeStringField(link.getTitle() + Constants.JSON_ASSOCIATION_LINK, link.getHref());
+        }
       }
     }
 
@@ -219,7 +225,7 @@ public class JsonSerializer implements ODataSerializer {
         valuable(jgen, annotation, link.getTitle() + "@" + annotation.getTerm());
       }
 
-      if (link.getHref() != null && !link.getHref().isEmpty()) {
+      if (link.getHref() != null && !link.getHref().isEmpty() && isODataMetadataFull) {
         jgen.writeStringField(link.getTitle() + Constants.JSON_NAVIGATION_LINK, link.getHref());
       }
 
@@ -313,7 +319,7 @@ public class JsonSerializer implements ODataSerializer {
       throws IOException, EdmPrimitiveTypeException {
     jgen.writeStartObject();
 
-    if (typeInfo != null && !isODataMetadataNone) {
+    if (typeInfo != null && isODataMetadataFull) {
       jgen.writeStringField(Constants.JSON_TYPE, typeInfo.external());
     }
 
@@ -360,7 +366,7 @@ public class JsonSerializer implements ODataSerializer {
           valuable.isPrimitive()) || valuable.isNull()) {
         type = EdmPrimitiveTypeKind.String.getFullQualifiedName().toString();
       }
-      if (type != null && !type.isEmpty() && !isODataMetadataNone) {
+      if (type != null && !type.isEmpty() && isODataMetadataFull) {
         jgen.writeStringField(
             name + Constants.JSON_TYPE,
             new EdmTypeInfo.Builder().setTypeExpression(type).build().external());
@@ -385,4 +391,10 @@ public class JsonSerializer implements ODataSerializer {
         && ContentType.VALUE_ODATA_METADATA_NONE.equalsIgnoreCase(
             contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA));
   }
+  
+  private boolean isODataMetadataFull() {
+    return contentType.isCompatible(ContentType.APPLICATION_JSON)
+        && ContentType.VALUE_ODATA_METADATA_FULL.equalsIgnoreCase(
+            contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA));
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
index 85607e7..ac4d770 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/AtomTest.java
@@ -84,7 +84,8 @@ public class AtomTest extends JSONTest {
   }
 
   @Override
-  protected void assertSimilar(final String filename, final String actual) throws Exception {
+  protected void assertSimilar(final String filename, final String actual, 
+      boolean isServerMode) throws Exception {
     final Diff diff = new Diff(cleanup(IOUtils.toString(getClass().getResourceAsStream(filename))), actual);
     diff.overrideElementQualifier(new AtomLinksQualifier());
     assertTrue(diff.similar());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
index e645f16..29a5222 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/JSONTest.java
@@ -45,6 +45,7 @@ import org.apache.olingo.client.api.domain.ClientProperty;
 import org.apache.olingo.client.api.domain.ClientValue;
 import org.apache.olingo.client.core.domain.ClientAnnotationImpl;
 import org.apache.olingo.client.core.serialization.JsonDeserializer;
+import org.apache.olingo.client.core.serialization.JsonSerializer;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.Delta;
@@ -75,13 +76,26 @@ public class JSONTest extends AbstractTest {
   protected ContentType getODataFormat() {
     return ContentType.JSON;
   }
+  
+  protected ContentType getODataMetadataFullFormat() {
+    return ContentType.JSON_FULL_METADATA;
+  }
+  
+  protected ContentType getODataMetadataNoneFormat() {
+    return ContentType.JSON_NO_METADATA;
+  }
 
-  private void cleanup(final ObjectNode node) {
-    if (node.has(Constants.JSON_CONTEXT)) {
-      node.remove(Constants.JSON_CONTEXT);
-    }
-    if (node.has(Constants.JSON_ETAG)) {
-      node.remove(Constants.JSON_ETAG);
+  private void cleanup(final ObjectNode node, boolean isServerMode) {
+    if (!isServerMode) {
+      if (node.has(Constants.JSON_CONTEXT)) {
+        node.remove(Constants.JSON_CONTEXT);
+      }
+      if (node.has(Constants.JSON_ETAG)) {
+        node.remove(Constants.JSON_ETAG);
+      }
+      if (node.has(Constants.JSON_COUNT)) {
+        node.remove(Constants.JSON_COUNT);
+      }
     }
     if (node.has(Constants.JSON_TYPE)) {
       node.remove(Constants.JSON_TYPE);
@@ -101,8 +115,8 @@ public class JSONTest extends AbstractTest {
     if (node.has(Constants.JSON_MEDIA_CONTENT_TYPE)) {
       node.remove(Constants.JSON_MEDIA_CONTENT_TYPE);
     }
-    if (node.has(Constants.JSON_COUNT)) {
-      node.remove(Constants.JSON_COUNT);
+    if (node.has(Constants.JSON_ID)) {
+      node.remove(Constants.JSON_ID);
     }
     final List<String> toRemove = new ArrayList<String>();
     for (final Iterator<Map.Entry<String, JsonNode>> itor = node.fields(); itor.hasNext();) {
@@ -114,16 +128,73 @@ public class JSONTest extends AbstractTest {
           || key.endsWith(Constants.JSON_MEDIA_EDIT_LINK)
           || key.endsWith(Constants.JSON_MEDIA_CONTENT_TYPE)
           || key.endsWith(Constants.JSON_ASSOCIATION_LINK)
+          || key.endsWith(Constants.JSON_MEDIA_ETAG)
+          || key.endsWith(Constants.JSON_BIND_LINK_SUFFIX)) {
+
+        toRemove.add(key);
+      } else if (field.getValue().isObject()) {
+        cleanup((ObjectNode) field.getValue(), false);
+      } else if (field.getValue().isArray()) {
+        for (final Iterator<JsonNode> arrayItems = field.getValue().elements(); arrayItems.hasNext();) {
+          final JsonNode arrayItem = arrayItems.next();
+          if (arrayItem.isObject()) {
+            cleanup((ObjectNode) arrayItem, false);
+          }
+        }
+      }
+    }
+    node.remove(toRemove);
+  }
+
+  private void cleanupWithFullMetadata(final ObjectNode node, boolean isServerMode) {
+    if (!isServerMode) {
+      if (node.has(Constants.JSON_CONTEXT)) {
+        node.remove(Constants.JSON_CONTEXT);
+      }
+      if (node.has(Constants.JSON_ETAG)) {
+        node.remove(Constants.JSON_ETAG);
+      }
+      if (node.has(Constants.JSON_COUNT)) {
+        node.remove(Constants.JSON_COUNT);
+      }
+      if (node.has(Constants.JSON_EDIT_LINK)) {
+        node.remove(Constants.JSON_EDIT_LINK);
+      }
+      if (node.has(Constants.JSON_MEDIA_READ_LINK)) {
+        node.remove(Constants.JSON_MEDIA_READ_LINK);
+      }
+    }
+    
+    if (node.has(Constants.JSON_READ_LINK)) {
+      node.remove(Constants.JSON_READ_LINK);
+    }
+    
+    if (node.has(Constants.JSON_MEDIA_CONTENT_TYPE)) {
+      node.remove(Constants.JSON_MEDIA_CONTENT_TYPE);
+    }
+    if (node.has(Constants.JSON_MEDIA_ETAG)) {
+      node.remove(Constants.JSON_MEDIA_ETAG);
+    }
+    final List<String> toRemove = new ArrayList<String>();
+    for (final Iterator<Map.Entry<String, JsonNode>> itor = node.fields(); itor.hasNext();) {
+      final Map.Entry<String, JsonNode> field = itor.next();
+
+      final String key = field.getKey();
+      if (key.charAt(0) == '#'
+          || (!isServerMode && key.endsWith(Constants.JSON_TYPE))
+          || (!isServerMode && key.endsWith(Constants.JSON_MEDIA_EDIT_LINK))
+          || key.endsWith(Constants.JSON_MEDIA_CONTENT_TYPE)
+          || (!isServerMode && key.endsWith(Constants.JSON_ASSOCIATION_LINK))
           || key.endsWith(Constants.JSON_MEDIA_ETAG)) {
 
         toRemove.add(key);
       } else if (field.getValue().isObject()) {
-        cleanup((ObjectNode) field.getValue());
+        cleanup((ObjectNode) field.getValue(), false);
       } else if (field.getValue().isArray()) {
         for (final Iterator<JsonNode> arrayItems = field.getValue().elements(); arrayItems.hasNext();) {
           final JsonNode arrayItem = arrayItems.next();
           if (arrayItem.isObject()) {
-            cleanup((ObjectNode) arrayItem);
+            cleanup((ObjectNode) arrayItem, false);
           }
         }
       }
@@ -131,21 +202,97 @@ public class JSONTest extends AbstractTest {
     node.remove(toRemove);
   }
 
-  protected void assertSimilar(final String filename, final String actual) throws Exception {
+  
+  private void cleanupWithNoMetadata(final ObjectNode node, boolean isServerMode) {
+    if (node.has(Constants.JSON_CONTEXT)) {
+      node.remove(Constants.JSON_CONTEXT);
+    }
+    if (node.has(Constants.JSON_ETAG)) {
+      node.remove(Constants.JSON_ETAG);
+    }
+    if (node.has(Constants.JSON_ID)) {
+      node.remove(Constants.JSON_ID);
+    }
+    if (node.has(Constants.JSON_EDIT_LINK)) {
+      node.remove(Constants.JSON_EDIT_LINK);
+    }
+    if (node.has(Constants.JSON_MEDIA_READ_LINK)) {
+      node.remove(Constants.JSON_MEDIA_READ_LINK);
+    }
+    if (node.has(Constants.JSON_READ_LINK)) {
+      node.remove(Constants.JSON_READ_LINK);
+    }
+    
+    if (node.has(Constants.JSON_MEDIA_CONTENT_TYPE)) {
+      node.remove(Constants.JSON_MEDIA_CONTENT_TYPE);
+    }
+    final List<String> toRemove = new ArrayList<String>();
+    for (final Iterator<Map.Entry<String, JsonNode>> itor = node.fields(); itor.hasNext();) {
+      final Map.Entry<String, JsonNode> field = itor.next();
+
+      final String key = field.getKey();
+      if (key.charAt(0) == '#'
+          || key.endsWith(Constants.JSON_TYPE)
+          || key.endsWith(Constants.JSON_MEDIA_EDIT_LINK)
+          || key.endsWith(Constants.JSON_MEDIA_CONTENT_TYPE)
+          || key.endsWith(Constants.JSON_ASSOCIATION_LINK)
+          || key.endsWith(Constants.JSON_MEDIA_ETAG)
+          || key.endsWith(Constants.JSON_BIND_LINK_SUFFIX)) {
+
+        toRemove.add(key);
+      } else if (field.getValue().isObject()) {
+        cleanup((ObjectNode) field.getValue(), false);
+      } else if (field.getValue().isArray()) {
+        for (final Iterator<JsonNode> arrayItems = field.getValue().elements(); arrayItems.hasNext();) {
+          final JsonNode arrayItem = arrayItems.next();
+          if (arrayItem.isObject()) {
+            cleanup((ObjectNode) arrayItem, false);
+          }
+        }
+      }
+    }
+    node.remove(toRemove);
+  }
+  
+  protected void assertSimilar(final String filename, final String actual, 
+      boolean isServerMode) throws Exception {
     final JsonNode expected = OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream(filename)).
         replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
-    cleanup((ObjectNode) expected);
+    cleanup((ObjectNode) expected, isServerMode);
     final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
-    cleanup(actualNode);
+    cleanup(actualNode, isServerMode);
+    assertEquals(expected, actualNode);
+  }
+  
+  protected void assertSimilarWithFullMetadata(final String filename, final String actual, 
+      boolean isServerMode) throws Exception {
+    String value = IOUtils.toString(getClass().getResourceAsStream(filename));
+    final JsonNode expected = isServerMode ? OBJECT_MAPPER.readTree(value.
+        replace(Constants.JSON_MEDIA_EDIT_LINK, Constants.JSON_MEDIA_READ_LINK)) :
+    OBJECT_MAPPER.readTree(value.
+        replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
+    cleanupWithFullMetadata((ObjectNode) expected, isServerMode);
+    final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    cleanupWithFullMetadata(actualNode, isServerMode);
+    assertEquals(expected, actualNode);
+  }
+  
+  protected void assertSimilarWithNoMetadata(final String filename, final String actual, 
+      boolean isServerMode) throws Exception {
+    final JsonNode expected = OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream(filename)).
+        replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
+    cleanupWithNoMetadata((ObjectNode) expected, isServerMode);
+    final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    cleanupWithNoMetadata(actualNode, isServerMode);
     assertEquals(expected, actualNode);
   }
 
   private void assertJSONSimilar(final String filename, final String actual) throws Exception {
     final JsonNode expected = OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream(filename)).
         replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
-    cleanup((ObjectNode) expected);
+    cleanup((ObjectNode) expected, false);
     final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
-    cleanup(actualNode);
+    cleanup(actualNode, false);
     assertEquals(expected, actualNode);
   }
   
@@ -154,22 +301,134 @@ public class JSONTest extends AbstractTest {
     client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
         getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
 
-    assertSimilar(filename + "." + getSuffix(contentType), writer.toString());
+    assertSimilar(filename + "." + getSuffix(contentType), writer.toString(), false);
+  }
+
+  protected void entitySetWithFullMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+
+    assertSimilarWithFullMetadata(filename + "." + getSuffix(contentType), writer.toString(), false);
   }
+  
+  protected void entitySetWithNoMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+
+    assertSimilarWithNoMetadata(filename + "." + getSuffix(contentType), writer.toString(), false);
+  }
+  
+  protected void entitySetInServerModeWithFullMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
 
+    assertSimilarWithFullMetadata(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
+  protected void entitySetInServerModeWithNoMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+
+    assertSimilarWithNoMetadata(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
+  protected void entitySetInServerMode(final String filename, final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    if (contentType == ContentType.JSON) {
+      new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
+          getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+    } else {
+      client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntitySet(
+          getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+    }
+    assertSimilar(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
   @Test
   public void entitySets() throws Exception {
     entitySet("Customers", getODataPubFormat());
+	entitySetInServerMode("Customers", getODataPubFormat());
     entitySet("collectionOfEntityReferences", getODataPubFormat());
+	entitySetInServerMode("collectionOfEntityReferences", getODataPubFormat());
+  }
+  
+  @Test
+  public void entitySetsWithFullMetadata() throws Exception {
+    entitySetWithFullMetadata("Customers", getODataMetadataFullFormat());
+    entitySetWithFullMetadata("collectionOfEntityReferences", getODataMetadataFullFormat());
+  }
+  
+  @Test
+  public void entitySetsWithFullMetadataInServerMode() throws Exception {
+    entitySetInServerModeWithFullMetadata("Customers_InServerMode", getODataMetadataFullFormat());
+  }
+  
+  @Test
+  public void entitySetsWithNoMetadata() throws Exception {
+    entitySetWithNoMetadata("Customers", getODataMetadataFullFormat());
+    entitySetInServerModeWithNoMetadata("Customers", getODataMetadataFullFormat());
+    entitySetWithNoMetadata("collectionOfEntityReferences", getODataMetadataFullFormat());
+    entitySetInServerModeWithNoMetadata("collectionOfEntityReferences", getODataMetadataFullFormat());
   }
 
   protected void entity(final String filename, final ContentType contentType) throws Exception {
     final StringWriter writer = new StringWriter();
     client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntity(
         getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
-    assertSimilar(filename + "." + getSuffix(contentType), writer.toString());
+    assertSimilar(filename + "." + getSuffix(contentType), writer.toString(), false);
   }
 
+  protected void entityWithFullMetadata(final String filename, final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntity(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+    assertSimilarWithFullMetadata(filename + "." + getSuffix(contentType), writer.toString(), false);
+  }
+  
+  protected void entityWithNoMetadata(final String filename, final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntity(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+    assertSimilarWithNoMetadata(filename + "." + getSuffix(contentType), writer.toString(), false);
+  }
+
+  
+  protected void entityInServerMode(final String filename, final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    if (contentType == ContentType.JSON) {
+      new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).toEntity(
+          getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+    } else {
+      client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).toEntity(
+          getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+    }
+    assertSimilar(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
+  protected void entityWithFullMetadataInServerMode(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).toEntity(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+    assertSimilarWithFullMetadata(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
+  protected void entityWithNoMetadataInServerMode(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).toEntity(
+        getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+    assertSimilarWithNoMetadata(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
   @Test
   public void additionalEntities() throws Exception {
     entity("entity.minimal", getODataPubFormat());
@@ -182,11 +441,49 @@ public class JSONTest extends AbstractTest {
   @Test
   public void entities() throws Exception {
     entity("Products_5", getODataPubFormat());
+    entityInServerMode("Products_5", getODataPubFormat());
     entity("VipCustomer", getODataPubFormat());
+    entityInServerMode("VipCustomer", getODataPubFormat());
     entity("Advertisements_f89dee73-af9f-4cd4-b330-db93c25ff3c7", getODataPubFormat());
+    entityInServerMode("Advertisements_f89dee73-af9f-4cd4-b330-db93c25ff3c7", getODataPubFormat());
     entity("entityReference", getODataPubFormat());
+    entityInServerMode("entityReference", getODataPubFormat());
     entity("entity.withcomplexnavigation", getODataPubFormat());
+    entityInServerMode("entity.withcomplexnavigation", getODataPubFormat());
     entity("annotated", getODataPubFormat());
+    entityInServerMode("annotated", getODataPubFormat());
+  }
+  
+  @Test
+  public void entitiesWithMetadataFull() throws Exception {
+    entityWithFullMetadata("Products_5", getODataMetadataFullFormat());
+    entityWithFullMetadata("VipCustomer", getODataMetadataFullFormat());
+    entityWithFullMetadata("Advertisements_f89dee73-af9f-4cd4-b330-db93c25ff3c7", 
+        getODataMetadataFullFormat());
+    entityWithFullMetadata("entityReference", getODataMetadataFullFormat());
+    entityWithFullMetadata("entity.withcomplexnavigation", getODataMetadataFullFormat());
+    entityWithFullMetadata("annotated", getODataMetadataFullFormat());
+  }
+  
+  @Test
+  public void entitiesWithMetadataFullInServerMode() throws Exception {
+    entityWithFullMetadataInServerMode("Products_5_InServerMode", getODataMetadataFullFormat());
+  }
+  
+  @Test
+  public void entitiesWithMetadataNone() throws Exception {
+    entityWithNoMetadata("Products_5", getODataMetadataNoneFormat());
+    entityWithNoMetadataInServerMode("Products_5", getODataMetadataNoneFormat());
+    entityWithNoMetadata("VipCustomer", getODataMetadataNoneFormat());
+    entityWithNoMetadataInServerMode("VipCustomer", getODataMetadataNoneFormat());
+    entityWithNoMetadata("Advertisements_f89dee73-af9f-4cd4-b330-db93c25ff3c7", 
+        getODataMetadataNoneFormat());
+    entityWithNoMetadataInServerMode("Advertisements_f89dee73-af9f-4cd4-b330-db93c25ff3c7", 
+        getODataMetadataNoneFormat());
+    entityWithNoMetadata("entityReference", getODataMetadataNoneFormat());
+    entityWithNoMetadataInServerMode("entityReference", getODataMetadataNoneFormat());
+    entityWithNoMetadata("entity.withcomplexnavigation", getODataMetadataNoneFormat());
+    entityWithNoMetadataInServerMode("entity.withcomplexnavigation", getODataMetadataNoneFormat());
   }
 
   protected void property(final String filename, final ContentType contentType) throws Exception {
@@ -194,15 +491,98 @@ public class JSONTest extends AbstractTest {
     client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).
         toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
 
-    assertSimilar(filename + "." + getSuffix(contentType), writer.toString());
+    assertSimilar(filename + "." + getSuffix(contentType), writer.toString(), false);
+  }
+
+  protected void propertyWithNoMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).
+        toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+
+    assertSimilarWithNoMetadata(filename + "." + getSuffix(contentType), writer.toString(), false);
+  }
+  
+  protected void propertyWithFullMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).
+        toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+
+    assertSimilarWithFullMetadata(filename + "." + getSuffix(contentType), writer.toString(), false);
   }
+  
+  protected void propertyInServerModeWithNoMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).
+        toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+
+    assertSimilarWithNoMetadata(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
+  protected void propertyInServerModeWithFullMetadata(final String filename, 
+      final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).
+        toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+
+    if (filename.equals("Products_5_SkinColor_NullType")) {
+      assertEquals(writer.toString(), "{\"@odata.context\":"
+          + "\"http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Products(5)/SkinColor\","
+          + "\"@odata.type\":\"String\",\"odata.null\":true}");
+    } else {
+      assertSimilarWithFullMetadata(filename + "." + getSuffix(contentType), writer.toString(), true);
+    }
+  }
+  
+  protected void propertyInServerMode(final String filename, final ContentType contentType) throws Exception {
+    final StringWriter writer = new StringWriter();
+    if (contentType == ContentType.JSON) {
+      new JsonSerializer(true, contentType).write(writer, client.getDeserializer(contentType).
+          toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))));
+    } else {
+      client.getSerializer(contentType).write(writer, client.getDeserializer(contentType).
+          toProperty(getClass().getResourceAsStream(filename + "." + getSuffix(contentType))).getPayload());
+    }
 
+    assertSimilar(filename + "." + getSuffix(contentType), writer.toString(), true);
+  }
+  
   @Test
   public void properties() throws Exception {
     property("Products_5_SkinColor", getODataFormat());
+    propertyInServerMode("Products_5_SkinColor", getODataFormat());
     property("Products_5_CoverColors", getODataFormat());
+    propertyInServerMode("Products_5_CoverColors", getODataFormat());
     property("Employees_3_HomeAddress", getODataFormat());
-    property("Employees_3_HomeAddress", getODataFormat());
+    propertyInServerMode("Employees_3_HomeAddress", getODataFormat());
+  }
+  
+  @Test
+  public void propertiesWithNoMetadata() throws Exception {
+    propertyWithNoMetadata("Products_5_SkinColor", getODataMetadataNoneFormat());
+    propertyInServerModeWithNoMetadata("Products_5_SkinColor", getODataMetadataNoneFormat());
+    propertyWithNoMetadata("Products_5_CoverColors", getODataMetadataNoneFormat());
+    propertyInServerModeWithNoMetadata("Products_5_CoverColors", getODataMetadataNoneFormat());
+    propertyWithNoMetadata("Employees_3_HomeAddress", getODataMetadataNoneFormat());
+    propertyInServerModeWithNoMetadata("Employees_3_HomeAddress", getODataMetadataNoneFormat());
+  }
+  
+  @Test
+  public void propertiesWithFullMetadata() throws Exception {
+    propertyWithFullMetadata("Products_5_SkinColor", getODataMetadataFullFormat());    
+    propertyWithFullMetadata("Products_5_CoverColors", getODataMetadataFullFormat());
+    propertyInServerModeWithFullMetadata("Products_5_CoverColors", getODataMetadataFullFormat());
+    propertyWithFullMetadata("Employees_3_HomeAddress", getODataMetadataFullFormat());
+  }
+  
+  @Test
+  public void propertiesWithFullMetadataInServerMode() throws Exception {
+    propertyInServerModeWithFullMetadata("Employees_3_HomeAddress_InServerMode", getODataMetadataFullFormat());
+    propertyInServerModeWithFullMetadata("Products_5_SkinColor_Null", getODataMetadataFullFormat());
+    propertyInServerModeWithFullMetadata("Products_5_SkinColor_NullType", getODataMetadataFullFormat());
+    propertyInServerModeWithFullMetadata("Products_5_SkinColor_PrimitiveType", getODataMetadataFullFormat());
   }
 
   @Test
@@ -268,11 +648,19 @@ public class JSONTest extends AbstractTest {
         client.getObjectFactory().newEnumValue("Microsoft.Exchange.Services.OData.Model.BodyType", "text")));
     message.getProperties().add(client.getObjectFactory().newComplexProperty("Body", body));
 
-    final String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
-    final JsonNode expected =
+    String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
+    JsonNode expected =
         OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo390.json")).
             replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
-    final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    cleanup((ObjectNode) expected, false);
+    ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    assertEquals(expected, actualNode);
+    
+    actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON_FULL_METADATA));
+    expected =
+        OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo390.json")).
+            replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
+    actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
     assertEquals(expected, actualNode);
   }
   
@@ -300,12 +688,19 @@ public class JSONTest extends AbstractTest {
     toRecipients.add(complType2);
     message.getProperties().add(client.getObjectFactory().newCollectionProperty("ToRecipients", toRecipients));
 
-
-    final String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
-    final JsonNode expected =
+	String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
+    JsonNode expected =
         OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo1073.json")).
             replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
-    final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    cleanup((ObjectNode) expected, false);
+    ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    assertEquals(expected, actualNode);
+    
+    actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON_FULL_METADATA));
+    expected =
+        OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo1073.json")).
+            replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
+    actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
     assertEquals(expected, actualNode);
   }
   
@@ -366,11 +761,19 @@ public class JSONTest extends AbstractTest {
     message.setEditLink(URI.create("http://services.odata.org/V4/(S(fe5rsnxo3fkkkk2bvmh1nl1y))/"
         + "TripPinServiceRW/People('russellwhyte')"));
 
-    final String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
-    final JsonNode expected =
+    String actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON));
+    JsonNode expected =
         OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo1073_1.json")).
             replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
-    final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    cleanup((ObjectNode) expected, false);
+    ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
+    assertEquals(expected, actualNode);
+    
+    actual = IOUtils.toString(client.getWriter().writeEntity(message, ContentType.JSON_FULL_METADATA));
+    expected =
+        OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream("olingo1073_1.json")).
+            replace(Constants.JSON_NAVIGATION_LINK, Constants.JSON_BIND_LINK_SUFFIX));
+    actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
     assertEquals(expected, actualNode);
   }
   
@@ -448,7 +851,7 @@ public class JSONTest extends AbstractTest {
     message.setEditLink(URI.create("http://services.odata.org/V4/(S(fe5rsnxo3fkkkk2bvmh1nl1y))/"
         + "TripPinServiceRW/People('russellwhyte')"));
 
-    InputStream inputStream = client.getWriter().writeEntity(message, ContentType.APPLICATION_JSON);
+    InputStream inputStream = client.getWriter().writeEntity(message, ContentType.JSON_FULL_METADATA);
     ResWrap<Entity> entity = new JsonDeserializer(true).toEntity(inputStream);
     assertNotNull(entity);
     assertEquals(7, entity.getPayload().getProperties().size());

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/CustomersWithFullMetadata.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/CustomersWithFullMetadata.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/CustomersWithFullMetadata.json
new file mode 100644
index 0000000..ff84d75
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/CustomersWithFullMetadata.json
@@ -0,0 +1,75 @@
+{
+  "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Customers",
+  "@odata.count": 2,
+  "value": [{
+      "@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)",
+      "@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)",
+      "PersonID@odata.type": "Int16",
+      "PersonID": 1,
+      "FirstName@odata.type": "String",
+      "FirstName": "Bob",
+      "LastName@odata.type": "String",
+      "LastName": "Cat",
+      "MiddleName@odata.type": "String",
+      "MiddleName": null,
+      "HomeAddress": {
+        "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress",
+        "Street": "1 Microsoft Way",
+        "City": "London",
+        "PostalCode": "98052",
+        "FamilyName": "Cats"
+      },
+      "Home": {
+        "type": "Point",
+        "coordinates": [23.1, 32.1],
+        "crs": {
+          "type": "name",
+          "properties": {
+            "name": "EPSG:4326"
+          }
+        }
+      },
+      "Numbers@odata.type": "#Collection(String)",
+      "Numbers": ["111-111-1111"],
+      "Emails@odata.type": "#Collection(String)",
+      "Emails": ["abc@abc.com"],
+      "City@odata.type": "String",
+      "City": "London",
+      "Birthday@odata.type": "DateTimeOffset",
+      "Birthday": "1957-04-03T00:00:00Z",
+      "TimeBetweenLastTwoOrders@odata.type": "Duration",
+      "TimeBetweenLastTwoOrders": "PT0.0000001S"
+    }, {
+      "@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)",
+      "@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)",
+      "PersonID@odata.type": "Int16",
+      "PersonID": 2,
+      "FirstName@odata.type": "String",
+      "FirstName": "Jill",
+      "LastName@odata.type": "String",
+      "LastName": "Jones",
+      "MiddleName@odata.type": "String",
+      "MiddleName": null,
+      "HomeAddress": null,
+      "Home": {
+        "type": "Point",
+        "coordinates": [161.8, 15.0],
+        "crs": {
+          "type": "name",
+          "properties": {
+            "name": "EPSG:4326"
+          }
+        }
+      },
+      "Numbers@odata.type": "#Collection(String)",
+      "Numbers": [],
+      "Emails@odata.type": "#Collection(String)",
+      "Emails": [],
+      "City@odata.type": "String",
+      "City": "Sydney",
+      "Birthday@odata.type": "DateTimeOffset",
+      "Birthday": "1983-01-15T00:00:00Z",
+      "TimeBetweenLastTwoOrders@odata.type": "Duration",
+      "TimeBetweenLastTwoOrders": "PT0.0000002S"
+    }]
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/Customers_InServerMode.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/Customers_InServerMode.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Customers_InServerMode.json
new file mode 100644
index 0000000..7c3cd83
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Customers_InServerMode.json
@@ -0,0 +1,135 @@
+{
+  "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Customers",
+  "@odata.metadataEtag": "W/\"4ca0a3ff-346c-43b1-afb3-ae9fc956343e\"",
+  "@odata.count": 2,
+  "@com.contoso.display.highlight": true,
+  "@com.contoso.PersonalInfo.PhoneNumbers": ["(203)555-1718", "(203)555-1719"],
+  "value": [{
+      "@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)",
+      "@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)",
+      "@odata.mediaEditLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(1)/$value",
+	  "@odata.mediaContentType": "*/*",
+	  "@odata.mediaEtag": "\"8zOOKKvgOtptr4gt8IrnapX3jds=\"",
+      "PersonID@odata.type": "Int32",
+      "PersonID": 1,
+      "FirstName@odata.type": "String",
+	  "FirstName@com.contoso.display.style": {
+	    "@odata.type": "#com.contoso.display.styleType",
+	    "title": true,
+	    "order": 1
+	  },
+      "FirstName": "Bob",
+      "LastName@odata.type": "String",
+      "LastName": "Cat",
+      "MiddleName@odata.type": "String",
+      "MiddleName": null,
+      "HomeAddress": {
+        "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress",
+        "Street@odata.type": "String",
+        "Street": "1 Microsoft Way",
+        "City@odata.type": "String",
+        "City": "London",
+        "PostalCode@odata.type": "String",
+        "PostalCode": "98052",
+        "FamilyName@odata.type": "String",
+        "FamilyName": "Cats",
+        "Country@odata.associationLink": "Customers(1)/HomeAddress/Country/$ref",
+        "Country@odata.navigationLink": "Customers(1)/HomeAddress/Country"
+      },
+      "Home@odata.type": "GeographyPoint",
+      "Home": {
+        "type": "Point",
+        "coordinates": [23.1, 32.1],
+        "crs": {
+          "type": "name",
+          "properties": {
+            "name": "EPSG:4326"
+          }
+        }
+      },
+      "Numbers": ["111-111-1111"],
+      "Emails": ["abc@abc.com"],
+      "City@odata.type": "String",
+      "City": "London",
+      "Birthday@odata.type": "DateTimeOffset",
+      "Birthday": "1957-04-03T00:00:00Z",
+      "TimeBetweenLastTwoOrders@odata.type": "Duration",
+      "TimeBetweenLastTwoOrders": "PT0.0000001S",
+      "Details@odata.associationLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(1)/Details/$ref",
+	  "Details@com.contoso.display.style": {
+		    "@odata.type": "#com.contoso.display.styleType",
+		    "order": 2
+	  	},
+	  	"Details@odata.navigationLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(1)/Details",
+	  	"Details": {
+	  		"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Details",
+	        "@odata.id": "Details(10)",
+	  		"Id@odata.type": "Int32",
+	  		"Id" : 10,
+	  		"Available@odata.type": "Boolean",
+	  		"Available" : false
+	  	}
+    }, {
+      "@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)",
+      "@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)",
+      "@odata.mediaEditLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(1)/$value",
+	  "@odata.mediaContentType": "*/*",
+	  "@odata.mediaEtag": "\"8zOOKKvgOtptr4gt8IrnapX3jds=\"",
+      "PersonID@odata.type": "Int32",
+      "PersonID": 2,
+      "FirstName@odata.type": "String",
+      "FirstName": "Jill",
+      "LastName@odata.type": "String",
+      "LastName": "Jones",
+      "MiddleName@odata.type": "String",
+      "MiddleName": null,
+      "HomeAddress": null,
+      "Home": {
+        "type": "Point",
+        "coordinates": [161.8, 15.0],
+        "crs": {
+          "type": "name",
+          "properties": {
+            "name": "EPSG:4326"
+          }
+        }
+      },
+      "Numbers": [],
+      "Emails": [],
+      "City@odata.type": "String",
+      "City": "Sydney",
+      "Birthday@odata.type": "DateTimeOffset",
+      "Birthday": "1983-01-15T00:00:00Z",
+      "TimeBetweenLastTwoOrders@odata.type": "Duration",
+      "TimeBetweenLastTwoOrders": "PT0.0000002S",
+      "Orders@odata.navigationLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(2)/Orders",
+	  "Orders" : [
+		  	{
+		  	"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Orders",
+		  	"@odata.id": "Orders(10)",
+		  	"OrderId@odata.type": "Int32",
+		  	"OrderId" : 10,
+		  	"Quantity@odata.type": "Int32",
+		  	"Quantity" : 2
+		  	},
+		  	{
+		  	"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Orders",
+		  	"@odata.id": "Orders(20)",
+		  	"OrderId@odata.type": "Int32",
+		  	"OrderId" : 20,
+		  	"Quantity@odata.type": "Int32",
+		  	"Quantity" : 2
+		  	}
+	  	],
+	  	"#Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight": {
+		"title": "Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight",
+		"target": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(2)/Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight"
+		},
+		"#Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails": {
+			"title": "Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails",
+			"target": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(2)/Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails"
+		}
+    }],
+     "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8015",
+     "@odata.nextLink": "Customers?$skiptoken=5"
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/Employees_3_HomeAddress_InServerMode.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/Employees_3_HomeAddress_InServerMode.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Employees_3_HomeAddress_InServerMode.json
new file mode 100644
index 0000000..05b65a9
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Employees_3_HomeAddress_InServerMode.json
@@ -0,0 +1,13 @@
+{
+  "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Employees(3)/HomeAddress",
+  "@com.contoso.display.highlight": true,
+  "@com.contoso.PersonalInfo.PhoneNumbers": ["(203)555-1718", "(203)555-1719"],
+  "Street@odata.type":"String",
+  "Street": "1 Microsoft Way",
+  "City@odata.type":"String",
+  "City": "Sydney",
+  "PostalCode@odata.type":"String",
+  "PostalCode": "98052",
+  "PinCode@odata.type":"String",
+  "PinCode": null
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_InServerMode.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_InServerMode.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_InServerMode.json
new file mode 100644
index 0000000..ff0fdb0
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_InServerMode.json
@@ -0,0 +1,104 @@
+{
+	"@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Products/$entity",
+	"@odata.metadataEtag": "W/\"3d81e743-9e4a-477e-9e7c-1e999edd13ce\"",
+	"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Product",
+	"@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)",
+	"@com.contoso.display.highlight": true,
+  	"@com.contoso.PersonalInfo.PhoneNumbers": ["(203)555-1718", "(203)555-1719"],
+	"ProductID@odata.type": "Int32",
+	"ProductID": 5,
+	"Name@odata.type": "String",
+	"Name@com.contoso.display.style": {
+	    "@odata.type": "#com.contoso.display.styleType",
+	    "title": true,
+	    "order": 1
+	  },
+	"Name": "Cheetos",
+	"QuantityPerUnit@odata.type": "String",
+	"QuantityPerUnit": "100g Bag",
+	"UnitPrice@odata.type": "Single",
+	"UnitPrice": 3.24,
+	"QuantityInStock@odata.type": "Int32",
+	"QuantityInStock": 100,
+	"Discontinued@odata.type": "Boolean",
+	"Discontinued": true,
+	"UserAccess@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.AccessLevel",
+	"UserAccess": "None",
+	"SkinColor@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Color",
+	"SkinColor": "Red",
+	"CoverColors@odata.type": "#Collection(Microsoft.Test.OData.Services.ODataWCFService.Color)",
+	"CoverColors": ["Green", "Blue", "Blue"],
+	"VendorAddress": {
+	    "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress",
+	    "Street@odata.type": "String",
+	    "Street": "1 Microsoft Way",
+	    "City@odata.type": "String",
+	    "City": "London",
+	    "PostalCode@odata.type": "String",
+	    "PostalCode": "98052",
+	    "VendorName@odata.type": "String",
+	    "VendorName": "Cats",
+	    "Country@odata.associationLink": "Products(5)/VendorAddress/Country/$ref",
+        "Country@odata.navigationLink": "Products(5)/VendorAddress/Country"
+	},
+	"Shop@odata.type": "GeographyPoint",
+	"Shop": {
+	    "type": "Point",
+	    "coordinates": [23.1, 32.1],
+	    "crs": {
+	      "type": "name",
+	      "properties": {
+	        "name": "EPSG:4326"
+	      }
+	    }
+	  },
+	"Time@odata.type": "DateTimeOffset",
+  	"Time": "1957-04-03T00:00:00Z",
+	"TimeBetweenLastTwoOrders@odata.type": "Duration",
+  	"TimeBetweenLastTwoOrders": "PT0.0000001S",
+	"@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)",
+	"@odata.mediaEditLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)/$value",
+	"@odata.mediaContentType": "*/*",
+	"@odata.mediaEtag": "\"8zOOKKvgOtptr4gt8IrnapX3jds=\"",
+	"Details@odata.associationLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)/Details/$ref",
+	"Details@com.contoso.display.style": {
+	    "@odata.type": "#com.contoso.display.styleType",
+	    "order": 2
+  	},
+  	"Details@odata.navigationLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)/Details",
+  	"Details": {
+  		"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Details",
+        "@odata.id": "Details(10)",
+  		"Id@odata.type": "Int32",
+  		"Id" : 10,
+  		"Available@odata.type": "Boolean",
+  		"Available" : false
+  	},
+  	"Orders@odata.navigationLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)/Orders",
+  	"Orders" : [
+	  	{
+	  	"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Orders",
+	  	"@odata.id": "Orders(10)",
+	  	"OrderId@odata.type": "Int32",
+	  	"OrderId" : 10,
+	  	"Quantity@odata.type": "Int32",
+	  	"Quantity" : 2
+	  	},
+	  	{
+	  	"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Orders",
+	  	"@odata.id": "Orders(20)",
+	  	"OrderId@odata.type": "Int32",
+	  	"OrderId" : 20,
+	  	"Quantity@odata.type": "Int32",
+	  	"Quantity" : 2
+	  	}
+  	],
+	"#Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight": {
+		"title": "Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight",
+		"target": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)/Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight"
+	},
+	"#Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails": {
+		"title": "Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails",
+		"target": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Products(5)/Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails"
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_Null.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_Null.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_Null.json
new file mode 100644
index 0000000..3792a4f
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_Null.json
@@ -0,0 +1,5 @@
+{
+  "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Products(5)/SkinColor",
+  "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Color",
+  "value": "null"
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_NullType.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_NullType.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_NullType.json
new file mode 100644
index 0000000..56f1ed9
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_NullType.json
@@ -0,0 +1,5 @@
+{
+  "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Products(5)/SkinColor",
+  "@odata.type": "String",
+  "value": null
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_PrimitiveType.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_PrimitiveType.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_PrimitiveType.json
new file mode 100644
index 0000000..ed42c3a
--- /dev/null
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/Products_5_SkinColor_PrimitiveType.json
@@ -0,0 +1,5 @@
+{
+  "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Products(5)/SkinColor",
+  "@odata.type": "String",
+  "value": "null"
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2696359f/lib/client-core/src/test/resources/org/apache/olingo/client/core/collectionOfEntityReferences.json
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/collectionOfEntityReferences.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/collectionOfEntityReferences.json
index 7646ee8..4463441 100644
--- a/lib/client-core/src/test/resources/org/apache/olingo/client/core/collectionOfEntityReferences.json
+++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/collectionOfEntityReferences.json
@@ -1,5 +1,6 @@
 {
   "@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Collection($ref)",
+  "@odata.count":2,
   "value": [
     {
       "@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/OrderDetails(OrderID=7,ProductID=5)"