[OLINGO-317] Support for JSON variants in server serializer

This commit is contained in:
Michael Bolz 2014-07-11 10:51:37 +02:00
parent cadd647616
commit 210cf9b37d
6 changed files with 82 additions and 63 deletions

View File

@ -22,8 +22,10 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.olingo.commons.api.ODataRuntimeException;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.commons.api.format.AcceptType;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.processor.CustomContentTypeSupportProcessor;
@ -34,8 +36,6 @@ import org.apache.olingo.server.api.uri.queryoption.FormatOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.dataformat.xml.util.TypeUtil;
public class ContentNegotiator {
private final static Logger LOG = LoggerFactory.getLogger(ContentNegotiator.class);
@ -49,9 +49,8 @@ public class ContentNegotiator {
if (processorClass == MetadataProcessor.class) {
defaults.add(new FormatContentTypeMapping("xml", ContentType.APPLICATION_XML.toContentTypeString()));
} else {
// defaults.add(new FormatContentTypeMapping("json", ContentType.APPLICATION_JSON.toContentTypeString()));
defaults.add(new FormatContentTypeMapping("json", ContentType.APPLICATION_JSON.toContentTypeString()
+ ";odata.metadata=minimal"));
defaults.add(new FormatContentTypeMapping("json",
ODataFormat.JSON.getContentType(ODataServiceVersion.V40).toContentTypeString()));
}
return defaults;
@ -84,7 +83,7 @@ public class ContentNegotiator {
if (formatOption != null) {
if ("json".equalsIgnoreCase(formatOption.getText().trim())) {
requestedContentType = ContentType.create(ContentType.APPLICATION_JSON, "odata.metadata=minimal");
requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40);
for (FormatContentTypeMapping entry : supportedContentTypes) {
if (requestedContentType.isCompatible(ContentType.create(entry.getContentType().trim()))) {
supported = true;
@ -136,7 +135,7 @@ public class ContentNegotiator {
}
if (requestedContentType == null) {
throw new RuntimeException("unsupported accept content type: " + acceptedContentTypes + " != "
throw new ODataRuntimeException("unsupported accept content type: " + acceptedContentTypes + " != "
+ supportedContentTypes);
}
} else {
@ -144,7 +143,7 @@ public class ContentNegotiator {
if (processorClass == MetadataProcessor.class) {
requestedContentType = ContentType.APPLICATION_XML;
} else {
requestedContentType = ContentType.create(ContentType.APPLICATION_JSON, "odata.metadata=minimal");
requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40);
}
for (FormatContentTypeMapping entry : supportedContentTypes) {
@ -156,7 +155,7 @@ public class ContentNegotiator {
}
if (!supported) {
throw new RuntimeException("unsupported accept content type: " + requestedContentType + " != "
throw new ODataRuntimeException("unsupported accept content type: " + requestedContentType + " != "
+ supportedContentTypes);
}

View File

@ -36,7 +36,9 @@ public class ODataImpl extends OData {
ODataSerializer serializer;
switch (format) {
case JSON:
serializer = new ODataJsonSerializer();
case JSON_NO_METADATA:
case JSON_FULL_METADATA:
serializer = new ODataJsonSerializer(format);
break;
case XML:
serializer = new ODataXmlSerializerImpl();

View File

@ -40,6 +40,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
@ -54,6 +55,12 @@ public class ODataJsonSerializer implements ODataSerializer {
private static final Logger log = LoggerFactory.getLogger(ODataJsonSerializer.class);
private final ODataFormat format;
public ODataJsonSerializer(final ODataFormat format) {
this.format = format;
}
@Override
public InputStream serviceDocument(final Edm edm, final String serviceRoot) {
CircleStreamBuffer buffer;
@ -100,6 +107,19 @@ public class ODataJsonSerializer implements ODataSerializer {
throw new ODataRuntimeException("Metadata in JSON format not supported!");
}
@Override
public InputStream error(final ODataError error) {
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
new ODataErrorSerializer().writeErrorDocument(json, error);
json.close();
} catch (final IOException e) {
throw new ODataRuntimeException(e);
}
return buffer.getInputStream();
}
@Override
public InputStream entitySet(final EdmEntitySet edmEntitySet, final EntitySet entitySet,
final ContextURL contextURL) {
@ -107,7 +127,7 @@ public class ODataJsonSerializer implements ODataSerializer {
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
json.writeStartObject();
if (contextURL != null) {
if (contextURL != null && format != ODataFormat.JSON_NO_METADATA) {
json.writeStringField(Constants.JSON_CONTEXT, contextURL.getURI().toASCIIString());
}
if (entitySet.getCount() != null) {
@ -149,17 +169,19 @@ public class ODataJsonSerializer implements ODataSerializer {
protected void writeEntity(final EdmEntityType entityType, final Entity entity, final ContextURL contextURL,
final JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
json.writeStartObject();
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT, contextURL.getURI().toASCIIString());
}
if (entity.getETag() != null) {
json.writeStringField("@odata.etag", entity.getETag());
}
if (entity.getMediaETag() != null) {
json.writeStringField("@odata.mediaEtag", entity.getMediaETag());
}
if (entity.getMediaContentType() != null) {
json.writeStringField("@odata.mediaContentType", entity.getMediaContentType());
if (format != ODataFormat.JSON_NO_METADATA) {
if (contextURL != null) {
json.writeStringField(Constants.JSON_CONTEXT, contextURL.getURI().toASCIIString());
}
if (entity.getETag() != null) {
json.writeStringField("@odata.etag", entity.getETag());
}
if (entity.getMediaETag() != null) {
json.writeStringField("@odata.mediaEtag", entity.getMediaETag());
}
if (entity.getMediaContentType() != null) {
json.writeStringField("@odata.mediaContentType", entity.getMediaContentType());
}
}
for (final String propertyName : entityType.getPropertyNames()) {
final EdmProperty edmProperty = (EdmProperty) entityType.getProperty(propertyName);
@ -185,7 +207,7 @@ public class ODataJsonSerializer implements ODataSerializer {
writePrimitive(edmProperty, property, json);
} else if (property.isLinkedComplex()) {
writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), json);
} else if (property.isComplex()) {
} else if(property.isComplex()) {
writeComplexValue(edmProperty, property.asComplex(), json);
} else {
throw new ODataRuntimeException("Property type not yet supported!");
@ -193,7 +215,6 @@ public class ODataJsonSerializer implements ODataSerializer {
}
}
private void writeCollection(EdmProperty edmProperty, Property property, JsonGenerator json)
throws IOException, EdmPrimitiveTypeException {
json.writeStartArray();
@ -257,7 +278,7 @@ public class ODataJsonSerializer implements ODataSerializer {
}
private void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
final EdmComplexType type = (EdmComplexType) edmProperty.getType();
json.writeStartObject();
for (final String propertyName : type.getPropertyNames()) {
@ -275,18 +296,4 @@ public class ODataJsonSerializer implements ODataSerializer {
}
return null;
}
@Override
public InputStream error(ODataError error) {
CircleStreamBuffer buffer = new CircleStreamBuffer();
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
ODataErrorSerializer ser = new ODataErrorSerializer();
ser.writeErrorDocument(json, error);
json.close();
} catch (final IOException e) {
throw new ODataRuntimeException(e);
}
return buffer.getInputStream();
}
}

View File

@ -66,7 +66,7 @@ public class TechnicalProcessor implements CollectionProcessor, EntityProcessor
response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
return;
}
ODataSerializer serializer = odata.createSerializer(ODataFormat.JSON);
ODataSerializer serializer = odata.createSerializer(ODataFormat.fromContentType(requestedContentType));
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
try {
final EntitySet entitySet = readEntitySetInternal(edmEntitySet, request.getRawBaseUri());
@ -90,7 +90,7 @@ public class TechnicalProcessor implements CollectionProcessor, EntityProcessor
response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
return;
}
ODataSerializer serializer = odata.createSerializer(ODataFormat.JSON);
ODataSerializer serializer = odata.createSerializer(ODataFormat.fromContentType(requestedContentType));
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
try {
final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet);

View File

@ -35,6 +35,7 @@ import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
import org.apache.olingo.server.tecsvc.provider.ContainerProvider;
@ -184,16 +185,12 @@ public class JsonDataProviderTest {
EntitySet outSet = jdp.readAll(entitySet);
ODataJsonSerializer serializer = new ODataJsonSerializer();
ODataJsonSerializer serializer = new ODataJsonSerializer(ODataFormat.JSON);
ContextURL contextUrl = null;
InputStream is = serializer.entitySet(entitySet, outSet, contextUrl);
StringHelper.Stream stream = StringHelper.toStream(is);
// System.out.println("========== " + entitySet.getName() + " =================");
// stream.print();
// System.out.println("\n========== " + entitySet.getName() + " =================");
Assert.assertEquals(expectedLength, stream.asString().length());
}
}

View File

@ -18,10 +18,10 @@
*/
package org.apache.olingo.server.core.serializer.json;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
@ -29,6 +29,7 @@ import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.tecsvc.data.DataProvider;
@ -42,7 +43,7 @@ public class ODataJsonSerializerTest {
private final EdmEntityContainer entityContainer = edm.getEntityContainer(
new FullQualifiedName("com.sap.odata.test1", "Container"));
private final DataProvider data = new DataProvider(edm);
private ODataSerializer serializer = new ODataJsonSerializer();
private ODataSerializer serializer = new ODataJsonSerializer(ODataFormat.JSON);
@Test
public void entitySimple() throws Exception {
@ -50,7 +51,7 @@ public class ODataJsonSerializerTest {
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
ContextURL.getInstance(URI.create("$metadata#ESAllPrim/$entity")));
final String resultString = streamToString(result);
final String resultString = IOUtils.toString(result);
final String expectedResult = "{"
+ "\"@odata.context\":\"$metadata#ESAllPrim/$entity\","
+ "\"PropertyInt16\":32767,"
@ -81,7 +82,7 @@ public class ODataJsonSerializerTest {
entitySet.setNext(URI.create("/next"));
InputStream result = serializer.entitySet(edmEntitySet, entitySet,
ContextURL.getInstance(URI.create("$metadata#ESAllPrim")));
final String resultString = streamToString(result);
final String resultString = IOUtils.toString(result);
Assert.assertTrue(resultString.matches("\\{"
+ "\"@odata\\.context\":\"\\$metadata#ESAllPrim\","
@ -104,7 +105,7 @@ public class ODataJsonSerializerTest {
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
ContextURL.getInstance(URI.create("$metadata#ESCollAllPrim/$entity")));
final String resultString = streamToString(result);
final String resultString = IOUtils.toString(result);
final String expectedResult = "{"
+ "\"@odata.context\":\"$metadata#ESCollAllPrim/$entity\","
+ "\"PropertyInt16\":1,"
@ -136,7 +137,7 @@ public class ODataJsonSerializerTest {
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
ContextURL.getInstance(URI.create("$metadata#ESCompAllPrim/$entity")));
final String resultString = streamToString(result);
final String resultString = IOUtils.toString(result);
final String expectedResult = "{"
+ "\"@odata.context\":\"$metadata#ESCompAllPrim/$entity\","
+ "\"PropertyInt16\":32767,"
@ -167,7 +168,7 @@ public class ODataJsonSerializerTest {
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity,
ContextURL.getInstance(URI.create("$metadata#ESMixPrimCollComp/$entity")));
final String resultString = streamToString(result);
final String resultString = IOUtils.toString(result);
final String expectedResult = "{"
+ "\"@odata.context\":\"$metadata#ESMixPrimCollComp/$entity\","
+ "\"PropertyInt16\":32767,"
@ -180,16 +181,29 @@ public class ODataJsonSerializerTest {
Assert.assertEquals(expectedResult, resultString);
}
private String streamToString(InputStream input) throws IOException {
byte[] buffer = new byte[8192];
StringBuilder result = new StringBuilder();
@Test
public void entityTwoPrimNoMetadata() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA)
.entity(edmEntitySet.getEntityType(), entity, ContextURL.getInstance(URI.create("contextURL")));
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}";
Assert.assertEquals(expectedResult, resultString);
}
int count = input.read(buffer);
while (count >= 0) {
result.append(new String(buffer, 0, count, "UTF-8"));
count = input.read(buffer);
}
return result.toString();
@Test
public void entitySetTwoPrimNoMetadata() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final EntitySet entitySet = data.readAll(edmEntitySet);
InputStream result = new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA)
.entitySet(edmEntitySet, entitySet, ContextURL.getInstance(URI.create("contextURL")));
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"value\":["
+ "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"
+ "{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"},"
+ "{\"PropertyInt16\":-32766,\"PropertyString\":\"Test String3\"},"
+ "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}";
Assert.assertEquals(expectedResult, resultString);
}
}