OLINGO-1009 Changing serialization to allow for $levels

This commit is contained in:
shawkins 2016-09-07 09:39:25 -04:00
parent b1db030cb8
commit 68969d547d
4 changed files with 202 additions and 64 deletions

View File

@ -64,6 +64,7 @@ import org.apache.olingo.server.api.uri.UriHelper;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.core.ODataWritableContent;
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
@ -73,6 +74,7 @@ import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper;
import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder;
import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
import org.apache.olingo.server.core.uri.UriHelperImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
@ -164,10 +166,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
writeOperations(entitySet.getOperations(), json);
json.writeFieldName(Constants.VALUE);
if (options == null) {
writeEntitySet(metadata, entityType, entitySet, null, null, false, json);
writeEntitySet(metadata, entityType, entitySet, null, null, null, false, json);
} else {
writeEntitySet(metadata, entityType, entitySet,
options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json);
options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), json);
}
writeNextLink(entitySet, json);
@ -210,10 +212,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
json.writeFieldName(Constants.VALUE);
if (options == null) {
writeEntitySet(metadata, entityType, entitySet, null, null, false, json);
writeEntitySet(metadata, entityType, entitySet, null, null, null, false, json);
} else {
writeEntitySet(metadata, entityType, entitySet,
options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json);
options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), json);
}
// next link not supported by default for streaming results
// writeNextLink(entitySet, json);
@ -238,6 +240,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
JsonGenerator json = new JsonFactory().createGenerator(outputStream);
writeEntity(metadata, entityType, entity, contextURL,
options == null ? null : options.getExpand(),
null,
options == null ? null : options.getSelect(),
options == null ? false : options.getWriteOnlyReferences(),
json);
@ -264,7 +267,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
final AbstractEntityCollection entitySet, final ExpandOption expand, final SelectOption select,
final AbstractEntityCollection entitySet, final ExpandOption expand, Integer toDepth, final SelectOption select,
final boolean onlyReference, final JsonGenerator json) throws IOException,
SerializerException {
json.writeStartArray();
@ -274,7 +277,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
json.writeStringField(Constants.JSON_ID, getEntityId(entity));
json.writeEndObject();
} else {
writeEntity(metadata, entityType, entity, null, expand, select, false, json);
writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, json);
}
}
json.writeEndArray();
@ -308,8 +311,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
public void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity,
final ContextURL contextURL, final ExpandOption expand, final SelectOption select, final boolean onlyReference,
final JsonGenerator json)
final ContextURL contextURL, final ExpandOption expand, Integer toDepth,
final SelectOption select, final boolean onlyReference, final JsonGenerator json)
throws IOException, SerializerException {
json.writeStartObject();
if (!isODataMetadataNone) {
@ -357,7 +360,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
writeProperties(metadata, resolvedType, entity.getProperties(), select, json);
writeNavigationProperties(metadata, resolvedType, entity, expand, json);
writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, json);
writeOperations(entity.getOperations(), json);
json.writeEndObject();
}
@ -442,24 +445,57 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
protected void writeNavigationProperties(final ServiceMetadata metadata,
final EdmStructuredType type, final Linked linked, final ExpandOption expand,
final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth,
final JsonGenerator json) throws SerializerException, IOException {
if (ExpandSelectHelper.hasExpand(expand)) {
final boolean expandAll = ExpandSelectHelper.isExpandAll(expand);
final Set<String> expanded = expandAll ? new HashSet<String>() :
ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems());
if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) {
final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand);
for (final String propertyName : type.getNavigationPropertyNames()) {
if (expandAll || expanded.contains(propertyName)) {
final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
if (toDepth != null) {
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
final Link navigationLink = linked.getNavigationLink(property.getName());
final ExpandItem innerOptions = expandAll ? null :
ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
if (innerOptions != null && innerOptions.getLevelsOption() != null) {
throw new SerializerException("Expand option $levels is not supported.",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
writeExpandedNavigationProperty(metadata, property, navigationLink,
innerOptions == null ? null : innerOptions.getExpandOption(),
expand, toDepth-1,
innerOptions == null ? null : innerOptions.getSelectOption(),
innerOptions == null ? null : innerOptions.getCountOption(),
innerOptions == null ? false : innerOptions.hasCountPath(),
innerOptions == null ? false : innerOptions.isRef(),
json);
continue;
}
Integer levels = null;
if (expandAll != null || innerOptions != null) {
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
final Link navigationLink = linked.getNavigationLink(property.getName());
ExpandOption childExpand = null;
LevelsExpandOption levelsOption = null;
if (innerOptions != null) {
levelsOption = innerOptions.getLevelsOption();
if (levelsOption == null) {
childExpand = innerOptions.getExpandOption();
} else {
ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
expandOptionImpl.addExpandItem(innerOptions);
childExpand = expandOptionImpl;
}
} else if (expandAll != null) {
levels = 1;
levelsOption = expandAll.getLevelsOption();
ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
expandOptionImpl.addExpandItem(expandAll);
childExpand = expandOptionImpl;
}
if (levelsOption != null) {
if (levelsOption.isMax()) {
levels = Integer.MAX_VALUE;
} else {
levels = levelsOption.getValue();
}
}
writeExpandedNavigationProperty(metadata, property, navigationLink,
childExpand, levels,
innerOptions == null ? null : innerOptions.getSelectOption(),
innerOptions == null ? null : innerOptions.getCountOption(),
innerOptions == null ? false : innerOptions.hasCountPath(),
@ -484,7 +520,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
protected void writeExpandedNavigationProperty(
final ServiceMetadata metadata, final EdmNavigationProperty property,
final Link navigationLink, final ExpandOption innerExpand,
final SelectOption innerSelect, final CountOption innerCount,
Integer toDepth, final SelectOption innerSelect, final CountOption innerCount,
final boolean writeOnlyCount, final boolean writeOnlyRef,
final JsonGenerator json) throws IOException, SerializerException {
@ -508,7 +544,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
writeInlineCount(property.getName(), navigationLink.getInlineEntitySet().getCount(), json);
}
json.writeFieldName(property.getName());
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand,
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth,
innerSelect, writeOnlyRef, json);
}
}
@ -518,7 +554,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
json.writeNull();
} else {
writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
innerExpand, innerSelect, writeOnlyRef, json);
innerExpand, toDepth, innerSelect, writeOnlyRef, json);
}
}
}
@ -847,7 +883,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
writeProperties(metadata, type, values, options == null ? null : options.getSelect(), json);
if (!property.isNull() && property.isComplex()) {
writeNavigationProperties(metadata, type, property.asComplex(),
options == null ? null : options.getExpand(), json);
options == null ? null : options.getExpand(), null, json);
}
json.writeEndObject();

View File

@ -121,7 +121,16 @@ public abstract class ExpandSelectHelper {
}
return false;
}
public static ExpandItem getExpandAll(final ExpandOption expand) {
for (final ExpandItem item : expand.getExpandItems()) {
if (item.isStar()) {
return item;
}
}
return null;
}
public static Set<String> getExpandedPropertyNames(final List<ExpandItem> expandItems)
throws SerializerException {
Set<String> expanded = new HashSet<String>();
@ -137,6 +146,9 @@ public abstract class ExpandSelectHelper {
public static ExpandItem getExpandItem(final List<ExpandItem> expandItems, final String propertyName) {
for (final ExpandItem item : expandItems) {
if (item.isStar()) {
continue;
}
final UriResource resource = item.getResourcePath().getUriResourceParts().get(0);
if (resource instanceof UriResourceNavigation
&& propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) {

View File

@ -70,6 +70,7 @@ import org.apache.olingo.server.api.serializer.SerializerStreamResult;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.core.ODataWritableContent;
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
@ -77,6 +78,7 @@ import org.apache.olingo.server.core.serializer.SerializerResultImpl;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder;
import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
public class ODataXmlSerializer extends AbstractODataSerializer {
@ -257,10 +259,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
if (options == null) {
writeEntitySet(metadata, entityType, entitySet, null, null, null, writer, writeOnlyRef);
writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef);
} else {
writeEntitySet(metadata, entityType, entitySet,
options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
options.getExpand(), null,
options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
}
writer.writeEndElement();
@ -314,10 +317,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
if (options == null) {
writeEntitySet(metadata, entityType, entitySet, null, null, null, writer, writeOnlyRef);
writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef);
} else {
writeEntitySet(metadata, entityType, entitySet,
options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
options.getExpand(), null,
options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
}
writer.writeEndElement();
@ -356,6 +360,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
writer.writeStartDocument(DEFAULT_CHARSET, "1.0");
writeEntity(metadata, entityType, entity, contextURL,
options == null ? null : options.getExpand(),
null,
options == null ? null : options.getSelect(),
options == null ? null : options.xml10InvalidCharReplacement(),
writer, true, false);
@ -397,17 +402,18 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
}
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
final AbstractEntityCollection entitySet, final ExpandOption expand, final SelectOption select,
final AbstractEntityCollection entitySet, final ExpandOption expand,
final Integer toDepth, final SelectOption select,
final String xml10InvalidCharReplacement,final XMLStreamWriter writer, final boolean writeOnlyRef)
throws XMLStreamException, SerializerException {
for (final Entity entity : entitySet) {
writeEntity(metadata, entityType, entity, null, expand, select,
writeEntity(metadata, entityType, entity, null, expand, toDepth, select,
xml10InvalidCharReplacement, writer, false, writeOnlyRef);
}
}
protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType,
final Entity entity, final ContextURL contextURL, final ExpandOption expand,
final Entity entity, final ContextURL contextURL, final ExpandOption expand, final Integer toDepth,
final SelectOption select, final String xml10InvalidCharReplacement,
final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef)
throws XMLStreamException, SerializerException {
@ -466,7 +472,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
}
EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType());
writeNavigationProperties(metadata, resolvedType, entity, expand, xml10InvalidCharReplacement, writer);
writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, xml10InvalidCharReplacement, writer);
writer.writeStartElement(ATOM, Constants.ATOM_ELEM_CATEGORY, NS_ATOM);
writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, Constants.NS_SCHEME);
@ -591,36 +597,71 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
}
protected void writeNavigationProperties(final ServiceMetadata metadata,
final EdmStructuredType type, final Linked linked, final ExpandOption expand,
final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth,
final String xml10InvalidCharReplacement, final XMLStreamWriter writer)
throws SerializerException, XMLStreamException {
if (ExpandSelectHelper.hasExpand(expand)) {
final boolean expandAll = ExpandSelectHelper.isExpandAll(expand);
final Set<String> expanded = expandAll ? new HashSet<String>() :
ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems());
if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) {
final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand);
for (final String propertyName : type.getNavigationPropertyNames()) {
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
final Link navigationLink = getOrCreateLink(linked, propertyName);
if (expandAll || expanded.contains(propertyName)) {
final ExpandItem innerOptions = expandAll ? null :
ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
if (innerOptions != null && innerOptions.getLevelsOption() != null) {
throw new SerializerException("Expand option $levels is not supported.",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
if (navigationLink != null) {
writeLink(writer, navigationLink, false);
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
writeExpandedNavigationProperty(metadata, property, navigationLink,
innerOptions == null ? null : innerOptions.getExpandOption(),
innerOptions == null ? null : innerOptions.getSelectOption(),
innerOptions == null ? null : innerOptions.getCountOption(),
innerOptions == null ? false : innerOptions.hasCountPath(),
innerOptions == null ? false : innerOptions.isRef(),
xml10InvalidCharReplacement, writer);
writer.writeEndElement();
writer.writeEndElement();
final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
if (toDepth != null) {
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
final Link navigationLink = getOrCreateLink(linked, propertyName);
writeLink(writer, navigationLink, false);
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
writeExpandedNavigationProperty(metadata, property, navigationLink,
expand, toDepth - 1,
innerOptions == null ? null : innerOptions.getSelectOption(),
innerOptions == null ? null : innerOptions.getCountOption(),
innerOptions == null ? false : innerOptions.hasCountPath(),
innerOptions == null ? false : innerOptions.isRef(),
xml10InvalidCharReplacement, writer);
writer.writeEndElement();
writer.writeEndElement();
continue;
}
Integer levels = null;
if (expandAll != null || innerOptions != null) {
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
final Link navigationLink = getOrCreateLink(linked, propertyName);
ExpandOption childExpand = null;
LevelsExpandOption levelsOption = null;
if (innerOptions != null) {
levelsOption = innerOptions.getLevelsOption();
if (levelsOption == null) {
childExpand = innerOptions.getExpandOption();
} else {
ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
expandOptionImpl.addExpandItem(innerOptions);
childExpand = expandOptionImpl;
}
} else if (expandAll != null) {
levels = 1;
levelsOption = expandAll.getLevelsOption();
ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl();
expandOptionImpl.addExpandItem(expandAll);
childExpand = expandOptionImpl;
}
if (levelsOption != null) {
if (levelsOption.isMax()) {
levels = Integer.MAX_VALUE;
} else {
levels = levelsOption.getValue();
}
}
writeLink(writer, navigationLink, false);
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
writeExpandedNavigationProperty(metadata, property, navigationLink,
childExpand, levels,
innerOptions == null ? null : innerOptions.getSelectOption(),
innerOptions == null ? null : innerOptions.getCountOption(),
innerOptions == null ? false : innerOptions.hasCountPath(),
innerOptions == null ? false : innerOptions.isRef(),
xml10InvalidCharReplacement, writer);
writer.writeEndElement();
writer.writeEndElement();
} else {
writeLink(writer, getOrCreateLink(linked, propertyName));
}
@ -676,7 +717,8 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
protected void writeExpandedNavigationProperty(final ServiceMetadata metadata,
final EdmNavigationProperty property, final Link navigationLink,
final ExpandOption innerExpand, final SelectOption innerSelect, final CountOption coutOption,
final ExpandOption innerExpand, final Integer toDepth,
final SelectOption innerSelect, final CountOption coutOption,
final boolean writeNavigationCount, final boolean writeOnlyRef,final String xml10InvalidCharReplacement,
final XMLStreamWriter writer) throws XMLStreamException, SerializerException {
if (property.isCollection()) {
@ -688,7 +730,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
if (coutOption != null && coutOption.getValue()) {
writeCount(navigationLink.getInlineEntitySet(), writer);
}
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand,
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth,
innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef);
}
writer.writeEndElement();
@ -696,7 +738,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
} else {
if (navigationLink != null && navigationLink.getInlineEntity() != null) {
writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
innerExpand, innerSelect, xml10InvalidCharReplacement, writer, false, writeOnlyRef);
innerExpand, toDepth, innerSelect, xml10InvalidCharReplacement, writer, false, writeOnlyRef);
}
}
}

View File

@ -65,6 +65,7 @@ import org.apache.olingo.server.api.uri.UriHelper;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectItem;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.core.serializer.ExpandSelectMock;
@ -1356,6 +1357,53 @@ public class ODataJsonSerializerTest {
+ "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}",
resultString);
}
@Test
public void expandStarTwoLevels() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final EdmEntityType entityType = edmEntitySet.getEntityType();
final EdmEntitySet innerEntitySet = entityContainer.getEntitySet("ESAllPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem expandItem = Mockito.mock(ExpandItem.class);
Mockito.when(expandItem.isStar()).thenReturn(true);
LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class);
Mockito.when(levels.getValue()).thenReturn(2);
Mockito.when(expandItem.getLevelsOption()).thenReturn(levels);
final SelectOption select = ExpandSelectMock.mockSelectOption(Collections.singletonList(
ExpandSelectMock.mockSelectItem(innerEntitySet, "PropertyInt32")));
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(expandItem));
final String resultString = IOUtils.toString(serializer
.entity(metadata, entityType, entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.selectList(helper.buildContextURLSelectList(entityType, expand, select))
.suffix(Suffix.ENTITY).build())
.expand(expand)
.build()).getContent());
Assert.assertEquals("{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\","
+ "\"NavPropertyETAllPrimOne\":null,"
+ "\"NavPropertyETAllPrimMany\":["
+ "{\"PropertyInt16\":-32768,\"PropertyString\":\"Second Resource - negative values\","
+ "\"PropertyBoolean\":false,\"PropertyByte\":0,\"PropertySByte\":-128,\"PropertyInt32\":-2147483648,"
+ "\"PropertyInt64\":-9223372036854775808,\"PropertySingle\":-1.79E8,\"PropertyDouble\":-179000.0,"
+ "\"PropertyDecimal\":-34,\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyDate\":\"2015-11-05\","
+ "\"PropertyDateTimeOffset\":\"2005-12-03T07:17:08Z\",\"PropertyDuration\":\"PT9S\","
+ "\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789dddfff\",\"PropertyTimeOfDay\":\"23:49:14\","
+ "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]},"
+ "{\"PropertyInt16\":0,\"PropertyString\":\"\",\"PropertyBoolean\":false,\"PropertyByte\":0,"
+ "\"PropertySByte\":0,\"PropertyInt32\":0,\"PropertyInt64\":0,\"PropertySingle\":0.0,"
+ "\"PropertyDouble\":0.0,\"PropertyDecimal\":0,\"PropertyBinary\":\"\","
+ "\"PropertyDate\":\"1970-01-01\",\"PropertyDateTimeOffset\":\"2005-12-03T00:00:00Z\","
+ "\"PropertyDuration\":\"PT0S\",\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789cccddd\","
+ "\"PropertyTimeOfDay\":\"00:01:01\",\"NavPropertyETTwoPrimOne\":null,"
+ "\"NavPropertyETTwoPrimMany\":["
+ "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"
+ "{\"PropertyInt16\":-32766,\"PropertyString\":null},"
+ "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}",
resultString);
}
@Test
public void primitiveProperty() throws Exception {