polishing
This commit is contained in:
parent
0f75cebdff
commit
d8e640d708
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -57,10 +57,11 @@ public class MarshallingMessageConverter implements MessageConverter, Initializi
|
|||
|
||||
private MessageType targetType = MessageType.BYTES;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new <code>MarshallingMessageConverter</code> with no {@link Marshaller} or {@link Unmarshaller} set.
|
||||
* The marshaller must be set after construction by invoking {@link #setMarshaller(Marshaller)} and
|
||||
* {@link #setUnmarshaller(Unmarshaller)} .
|
||||
* Construct a new <code>MarshallingMessageConverter</code> with no {@link Marshaller}
|
||||
* or {@link Unmarshaller} set. The marshaller must be set after construction by invoking
|
||||
* {@link #setMarshaller(Marshaller)} and {@link #setUnmarshaller(Unmarshaller)} .
|
||||
*/
|
||||
public MarshallingMessageConverter() {
|
||||
}
|
||||
|
|
@ -80,7 +81,7 @@ public class MarshallingMessageConverter implements MessageConverter, Initializi
|
|||
if (!(marshaller instanceof Unmarshaller)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Marshaller [" + marshaller + "] does not implement the Unmarshaller " +
|
||||
"interface. Please set an Unmarshaller explicitely by using the " +
|
||||
"interface. Please set an Unmarshaller explicitly by using the " +
|
||||
"MarshallingMessageConverter(Marshaller, Unmarshaller) constructor.");
|
||||
}
|
||||
else {
|
||||
|
|
@ -127,6 +128,7 @@ public class MarshallingMessageConverter implements MessageConverter, Initializi
|
|||
* @see MessageType#TEXT
|
||||
*/
|
||||
public void setTargetType(MessageType targetType) {
|
||||
Assert.notNull(targetType, "MessageType must not be null");
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
|
|
@ -251,8 +253,8 @@ public class MarshallingMessageConverter implements MessageConverter, Initializi
|
|||
protected Message marshalToMessage(Object object, Session session, Marshaller marshaller, MessageType targetType)
|
||||
throws JMSException, IOException, XmlMappingException {
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported message type [" + targetType + "]. Cannot marshal to the specified message type.");
|
||||
throw new IllegalArgumentException("Unsupported message type [" + targetType +
|
||||
"]. MarshallingMessageConverter by default only supports TextMessages and BytesMessages.");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -308,8 +310,8 @@ public class MarshallingMessageConverter implements MessageConverter, Initializi
|
|||
protected Object unmarshalFromMessage(Message message, Unmarshaller unmarshaller)
|
||||
throws JMSException, IOException, XmlMappingException {
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"MarshallingMessageConverter only supports TextMessages and BytesMessages");
|
||||
throw new IllegalArgumentException("Unsupported message type [" + message.getClass() +
|
||||
"]. MarshallingMessageConverter by default only supports TextMessages and BytesMessages.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -110,11 +110,12 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the XStream instance used by this marshaller.
|
||||
*/
|
||||
public XStream getXStream() {
|
||||
return xstream;
|
||||
return this.xstream;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -150,7 +151,6 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
/**
|
||||
* Sets an alias/type map, consisting of string aliases mapped to classes. Keys are aliases; values are either
|
||||
* {@code Class} instances, or String class names.
|
||||
*
|
||||
* @see XStream#alias(String, Class)
|
||||
*/
|
||||
public void setAliases(Map<String, ?> aliases) throws ClassNotFoundException {
|
||||
|
|
@ -165,7 +165,6 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
* Sets the aliases by type map, consisting of string aliases mapped to classes. Any class that is assignable to
|
||||
* this type will be aliased to the same name. Keys are aliases; values are either
|
||||
* {@code Class} instances, or String class names.
|
||||
*
|
||||
* @see XStream#aliasType(String, Class)
|
||||
*/
|
||||
public void setAliasesByType(Map<String, ?> aliases) throws ClassNotFoundException {
|
||||
|
|
@ -325,9 +324,9 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the auto-detection mode of XStream.
|
||||
* <p><strong>Note</strong> that auto-detection implies that the XStream is configured while it is processing the
|
||||
* XML steams, and thus introduces a potential concurrency problem.
|
||||
* Set the autodetection mode of XStream.
|
||||
* <p><strong>Note</strong> that auto-detection implies that the XStream is configured while
|
||||
* it is processing the XML streams, and thus introduces a potential concurrency problem.
|
||||
* @see XStream#autodetectAnnotations(boolean)
|
||||
*/
|
||||
public void setAutodetectAnnotations(boolean autodetectAnnotations) {
|
||||
|
|
@ -358,22 +357,24 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
this.supportedClasses = supportedClasses;
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
customizeXStream(getXStream());
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
customizeXStream(getXStream());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to allow for customizing of the given {@link XStream}.
|
||||
* <p>Default implementation is empty.
|
||||
* <p>The default implementation is empty.
|
||||
* @param xstream the {@code XStream} instance
|
||||
*/
|
||||
protected void customizeXStream(XStream xstream) {
|
||||
}
|
||||
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
if (ObjectUtils.isEmpty(this.supportedClasses)) {
|
||||
return true;
|
||||
|
|
@ -438,8 +439,8 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
|
||||
@Override
|
||||
protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
|
||||
if (streamDriver != null) {
|
||||
marshal(graph, streamDriver.createWriter(writer));
|
||||
if (this.streamDriver != null) {
|
||||
marshal(graph, this.streamDriver.createWriter(writer));
|
||||
}
|
||||
else {
|
||||
marshal(graph, new CompactWriter(writer));
|
||||
|
|
@ -467,6 +468,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Unmarshalling
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -20,7 +20,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
|
@ -28,6 +27,7 @@ import org.codehaus.jackson.JsonEncoding;
|
|||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.SerializerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
|
@ -35,19 +35,18 @@ import org.springframework.web.servlet.View;
|
|||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
/**
|
||||
* Spring-MVC {@link View} that renders JSON content by serializing the model for the current request using <a
|
||||
* href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}.
|
||||
* Spring MVC {@link View} that renders JSON content by serializing the model for the current request
|
||||
* using <a href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}.
|
||||
*
|
||||
* <p>By default, the entire contents of the model map (with the exception of framework-specific classes) will be
|
||||
* encoded as JSON. If the model contains only one key, you can have it extracted encoded as JSON alone via
|
||||
* {@link #setExtractValueFromSingleKeyModel(boolean)}. Or you can select specific model attributes to be encoded
|
||||
* as JSON via ... TODO
|
||||
* <p>By default, the entire contents of the model map (with the exception of framework-specific classes)
|
||||
* will be encoded as JSON. If the model contains only one key, you can have it extracted encoded as JSON
|
||||
* alone via {@link #setExtractValueFromSingleKeyModel}.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @see org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
|
||||
* @since 3.0
|
||||
* @see org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
|
||||
*/
|
||||
public class MappingJacksonJsonView extends AbstractView {
|
||||
|
||||
|
|
@ -56,6 +55,7 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
*/
|
||||
public static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private JsonEncoding encoding = JsonEncoding.UTF8;
|
||||
|
|
@ -68,6 +68,7 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
|
||||
private boolean disableCaching = true;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new {@code JacksonJsonView}, setting the content type to {@code application/json}.
|
||||
*/
|
||||
|
|
@ -76,14 +77,15 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
setExposePathVariables(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the {@code ObjectMapper} for this view. If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper}
|
||||
* is used.
|
||||
*
|
||||
* <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of the JSON serialization
|
||||
* process. For example, an extended {@link SerializerFactory} can be configured that provides custom serializers for
|
||||
* specific types. The other option for refining the serialization process is to use Jackson's provided annotations on
|
||||
* the types to be serialized, in which case a custom-configured ObjectMapper is unnecessary.
|
||||
* Sets the {@code ObjectMapper} for this view.
|
||||
* If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
|
||||
* <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control
|
||||
* of the JSON serialization process. For example, an extended {@link SerializerFactory}
|
||||
* can be configured that provides custom serializers for specific types. The other option
|
||||
* for refining the serialization process is to use Jackson's provided annotations on the
|
||||
* types to be serialized, in which case a custom-configured ObjectMapper is unnecessary.
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "'objectMapper' must not be null");
|
||||
|
|
@ -91,7 +93,8 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code JsonEncoding} for this converter. By default, {@linkplain JsonEncoding#UTF8 UTF-8} is used.
|
||||
* Set the {@code JsonEncoding} for this converter.
|
||||
* By default, {@linkplain JsonEncoding#UTF8 UTF-8} is used.
|
||||
*/
|
||||
public void setEncoding(JsonEncoding encoding) {
|
||||
Assert.notNull(encoding, "'encoding' must not be null");
|
||||
|
|
@ -99,18 +102,19 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the JSON output by this view should be prefixed with <tt>"{} && "</tt>. Default is false.
|
||||
*
|
||||
* <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string
|
||||
* syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON,
|
||||
* but if JSON validation is performed on the string, the prefix would need to be ignored.
|
||||
* Indicates whether the JSON output by this view should be prefixed with <tt>"{} && "</tt>.
|
||||
* Default is false.
|
||||
* <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.
|
||||
* The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
|
||||
* This prefix does not affect the evaluation of JSON, but if JSON validation is performed
|
||||
* on the string, the prefix would need to be ignored.
|
||||
*/
|
||||
public void setPrefixJson(boolean prefixJson) {
|
||||
this.prefixJson = prefixJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute in the model that should be rendered by this view.
|
||||
* Set the attribute in the model that should be rendered by this view.
|
||||
* When set, all other model attributes will be ignored.
|
||||
*/
|
||||
public void setModelKey(String modelKey) {
|
||||
|
|
@ -118,7 +122,7 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes in the model that should be rendered by this view.
|
||||
* Set the attributes in the model that should be rendered by this view.
|
||||
* When set, all other model attributes will be ignored.
|
||||
*/
|
||||
public void setModelKeys(Set<String> modelKeys) {
|
||||
|
|
@ -126,56 +130,56 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the attributes in the model that should be rendered by this view.
|
||||
* Return the attributes in the model that should be rendered by this view.
|
||||
*/
|
||||
public Set<String> getModelKeys() {
|
||||
return modelKeys;
|
||||
return this.modelKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes in the model that should be rendered by this view.
|
||||
* Set the attributes in the model that should be rendered by this view.
|
||||
* When set, all other model attributes will be ignored.
|
||||
* @deprecated use {@link #setModelKeys(Set)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setRenderedAttributes(Set<String> renderedAttributes) {
|
||||
this.modelKeys = renderedAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attributes in the model that should be rendered by this view.
|
||||
* Return the attributes in the model that should be rendered by this view.
|
||||
* @deprecated use {@link #getModelKeys()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Set<String> getRenderedAttributes() {
|
||||
return modelKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables caching of the generated JSON.
|
||||
*
|
||||
* <p>Default is {@code true}, which will prevent the client from caching the generated JSON.
|
||||
*/
|
||||
public void setDisableCaching(boolean disableCaching) {
|
||||
this.disableCaching = disableCaching;
|
||||
return this.modelKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to serialize models containing a single attribute as a map or whether to
|
||||
* extract the single value from the model and serialize it directly.
|
||||
* The effect of setting this flag is similar to using
|
||||
* {@code MappingJacksonHttpMessageConverter} with an {@code @ResponseBody}.
|
||||
* request-handling method.
|
||||
*
|
||||
* <p>The effect of setting this flag is similar to using {@code MappingJacksonHttpMessageConverter}
|
||||
* with an {@code @ResponseBody} request-handling method.
|
||||
* <p>Default is {@code false}.
|
||||
*/
|
||||
public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyModel) {
|
||||
this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables caching of the generated JSON.
|
||||
* <p>Default is {@code true}, which will prevent the client from caching the generated JSON.
|
||||
*/
|
||||
public void setDisableCaching(boolean disableCaching) {
|
||||
this.disableCaching = disableCaching;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
|
||||
response.setContentType(getContentType());
|
||||
response.setCharacterEncoding(encoding.getJavaName());
|
||||
if (disableCaching) {
|
||||
response.setCharacterEncoding(this.encoding.getJavaName());
|
||||
if (this.disableCaching) {
|
||||
response.addHeader("Pragma", "no-cache");
|
||||
response.addHeader("Cache-Control", "no-cache, no-store, max-age=0");
|
||||
response.addDateHeader("Expires", 1L);
|
||||
|
|
@ -183,38 +187,35 @@ public class MappingJacksonJsonView extends AbstractView {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void renderMergedOutputModel(Map<String, Object> model,
|
||||
HttpServletRequest request,
|
||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
|
||||
HttpServletResponse response) throws Exception {
|
||||
|
||||
Object value = filterModel(model);
|
||||
JsonGenerator generator =
|
||||
objectMapper.getJsonFactory().createJsonGenerator(response.getOutputStream(), encoding);
|
||||
if (prefixJson) {
|
||||
this.objectMapper.getJsonFactory().createJsonGenerator(response.getOutputStream(), this.encoding);
|
||||
if (this.prefixJson) {
|
||||
generator.writeRaw("{} && ");
|
||||
}
|
||||
objectMapper.writeValue(generator, value);
|
||||
this.objectMapper.writeValue(generator, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out undesired attributes from the given model. The return value can be either another {@link Map}, or a
|
||||
* single value object.
|
||||
*
|
||||
* <p>Default implementation removes {@link BindingResult} instances and entries not included in the {@link
|
||||
* #setRenderedAttributes(Set) renderedAttributes} property.
|
||||
*
|
||||
* Filters out undesired attributes from the given model.
|
||||
* The return value can be either another {@link Map} or a single value object.
|
||||
* <p>The default implementation removes {@link BindingResult} instances and entries
|
||||
* not included in the {@link #setRenderedAttributes renderedAttributes} property.
|
||||
* @param model the model, as passed on to {@link #renderMergedOutputModel}
|
||||
* @return the object to be rendered
|
||||
*/
|
||||
protected Object filterModel(Map<String, Object> model) {
|
||||
Map<String, Object> result = new HashMap<String, Object>(model.size());
|
||||
Set<String> renderedAttributes =
|
||||
!CollectionUtils.isEmpty(this.modelKeys) ? this.modelKeys : model.keySet();
|
||||
Set<String> renderedAttributes = (!CollectionUtils.isEmpty(this.modelKeys) ? this.modelKeys : model.keySet());
|
||||
for (Map.Entry<String, Object> entry : model.entrySet()) {
|
||||
if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) {
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return (this.extractValueFromSingleKeyModel && result.size() == 1) ? result.values().iterator().next() : result;
|
||||
return (this.extractValueFromSingleKeyModel && result.size() == 1 ? result.values().iterator().next() : result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -474,7 +474,6 @@ public class MediaType implements Comparable<MediaType> {
|
|||
int otherPlusIdx = other.subtype.indexOf('+');
|
||||
if (thisPlusIdx != -1 && otherPlusIdx != -1) {
|
||||
String thisSubtypeNoSuffix = this.subtype.substring(0, thisPlusIdx);
|
||||
|
||||
String thisSubtypeSuffix = this.subtype.substring(thisPlusIdx + 1);
|
||||
String otherSubtypeSuffix = other.subtype.substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix.equals(otherSubtypeSuffix) && WILDCARD_TYPE.equals(thisSubtypeNoSuffix)) {
|
||||
|
|
|
|||
|
|
@ -16,16 +16,13 @@
|
|||
|
||||
package org.springframework.http.converter.json;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
import org.codehaus.jackson.JsonEncoding;
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.JsonParseException;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.codehaus.jackson.JsonProcessingException;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.type.TypeFactory;
|
||||
import org.codehaus.jackson.type.JavaType;
|
||||
|
|
@ -55,6 +52,7 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
|
|||
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private boolean prefixJson = false;
|
||||
|
|
@ -106,27 +104,6 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
|
|||
return (this.objectMapper.canDeserialize(javaType) && canRead(mediaType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Jackson {@link JavaType} for the specific class.
|
||||
* <p>The default implementation returns {@link TypeFactory#type(java.lang.reflect.Type)},
|
||||
* but this can be overridden in subclasses, to allow for custom generic collection handling.
|
||||
* For instance:
|
||||
* <pre class="code">
|
||||
* protected JavaType getJavaType(Class<?> clazz) {
|
||||
* if (List.class.isAssignableFrom(clazz)) {
|
||||
* return TypeFactory.collectionType(ArrayList.class, MyBean.class);
|
||||
* } else {
|
||||
* return super.getJavaType(clazz);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @param clazz the class to return the java type for
|
||||
* @return the java type
|
||||
*/
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
return TypeFactory.type(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||
return (this.objectMapper.canSerialize(clazz) && canWrite(mediaType));
|
||||
|
|
@ -146,36 +123,57 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
|
|||
try {
|
||||
return this.objectMapper.readValue(inputMessage.getBody(), javaType);
|
||||
}
|
||||
catch (JsonParseException ex) {
|
||||
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
|
||||
}
|
||||
catch (JsonMappingException ex) {
|
||||
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
|
||||
}
|
||||
catch (EOFException ex) {
|
||||
catch (JsonProcessingException ex) {
|
||||
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
|
||||
protected void writeInternal(Object object, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType());
|
||||
JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
|
||||
JsonGenerator jsonGenerator =
|
||||
this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
|
||||
try {
|
||||
if (this.prefixJson) {
|
||||
jsonGenerator.writeRaw("{} && ");
|
||||
}
|
||||
this.objectMapper.writeValue(jsonGenerator, o);
|
||||
this.objectMapper.writeValue(jsonGenerator, object);
|
||||
}
|
||||
catch (JsonGenerationException ex) {
|
||||
catch (JsonProcessingException ex) {
|
||||
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonEncoding getEncoding(MediaType contentType) {
|
||||
|
||||
/**
|
||||
* Return the Jackson {@link JavaType} for the specified class.
|
||||
* <p>The default implementation returns {@link TypeFactory#type(java.lang.reflect.Type)},
|
||||
* but this can be overridden in subclasses, to allow for custom generic collection handling.
|
||||
* For instance:
|
||||
* <pre class="code">
|
||||
* protected JavaType getJavaType(Class<?> clazz) {
|
||||
* if (List.class.isAssignableFrom(clazz)) {
|
||||
* return TypeFactory.collectionType(ArrayList.class, MyBean.class);
|
||||
* } else {
|
||||
* return super.getJavaType(clazz);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @param clazz the class to return the java type for
|
||||
* @return the java type
|
||||
*/
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
return TypeFactory.type(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the JSON encoding to use for the given content type.
|
||||
* @param contentType the media type as requested by the caller
|
||||
* @return the JSON encoding to use (never <code>null</code>)
|
||||
*/
|
||||
protected JsonEncoding getJsonEncoding(MediaType contentType) {
|
||||
if (contentType != null && contentType.getCharSet() != null) {
|
||||
Charset charset = contentType.getCharSet();
|
||||
for (JsonEncoding encoding : JsonEncoding.values()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue