com.alibaba.fastjson.support.spring.FastJsonJsonView Maven / Gradle / Ivy
Show all versions of fastjson Show documentation
package com.alibaba.fastjson.support.spring;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPObject;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.util.IOUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Fastjson for Spring MVC View.
*
* @author [email protected]
* @author VictorZeng
* @see AbstractView
* @since 1.2.9
*/
public class FastJsonJsonView extends AbstractView {
/**
* default content type
*/
public static final String DEFAULT_CONTENT_TYPE = "application/json;charset=UTF-8";
/**
* Default content type for JSONP: "application/javascript".
*/
public static final String DEFAULT_JSONP_CONTENT_TYPE = "application/javascript";
/**
* Pattern for validating jsonp callback parameter values.
*/
private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
@Deprecated
protected Charset charset = Charset.forName("UTF-8");
@Deprecated
protected SerializerFeature[] features = new SerializerFeature[0];
@Deprecated
protected SerializeFilter[] filters = new SerializeFilter[0];
@Deprecated
protected String dateFormat;
/**
* renderedAttributes
*/
private Set renderedAttributes;
/**
* disableCaching
*/
private boolean disableCaching = true;
/**
* updateContentLength
*/
private boolean updateContentLength = true;
/**
* extractValueFromSingleKeyModel
*/
private boolean extractValueFromSingleKeyModel = false;
/**
* with fastJson config
*/
private FastJsonConfig fastJsonConfig = new FastJsonConfig();
/**
* jsonp parameter name
*/
private String[] jsonpParameterNames = {"jsonp", "callback"};
/**
* Set default param.
*/
public FastJsonJsonView() {
setContentType(DEFAULT_CONTENT_TYPE);
setExposePathVariables(false);
}
/**
* @return the fastJsonConfig.
* @since 1.2.11
*/
public FastJsonConfig getFastJsonConfig() {
return fastJsonConfig;
}
/**
* @param fastJsonConfig the fastJsonConfig to set.
* @since 1.2.11
*/
public void setFastJsonConfig(FastJsonConfig fastJsonConfig) {
this.fastJsonConfig = fastJsonConfig;
}
/**
* Sets serializer feature.
*
* @param features the features
* @see FastJsonConfig#setSerializerFeatures(SerializerFeature...)
* @deprecated
*/
@Deprecated
public void setSerializerFeature(SerializerFeature... features) {
this.fastJsonConfig.setSerializerFeatures(features);
}
/**
* Gets charset.
*
* @return the charset
* @see FastJsonConfig#getCharset()
* @deprecated
*/
@Deprecated
public Charset getCharset() {
return this.fastJsonConfig.getCharset();
}
/**
* Sets charset.
*
* @param charset the charset
* @see FastJsonConfig#setCharset(Charset)
* @deprecated
*/
@Deprecated
public void setCharset(Charset charset) {
this.fastJsonConfig.setCharset(charset);
}
/**
* Gets date format.
*
* @return the date format
* @see FastJsonConfig#getDateFormat()
* @deprecated
*/
@Deprecated
public String getDateFormat() {
return this.fastJsonConfig.getDateFormat();
}
/**
* Sets date format.
*
* @param dateFormat the date format
* @see FastJsonConfig#setDateFormat(String)
* @deprecated
*/
@Deprecated
public void setDateFormat(String dateFormat) {
this.fastJsonConfig.setDateFormat(dateFormat);
}
/**
* Get features serializer feature [].
*
* @return the serializer feature []
* @see FastJsonConfig#getSerializerFeatures()
* @deprecated
*/
@Deprecated
public SerializerFeature[] getFeatures() {
return this.fastJsonConfig.getSerializerFeatures();
}
/**
* Sets features.
*
* @param features the features
* @see FastJsonConfig#setSerializerFeatures(SerializerFeature...)
* @deprecated
*/
@Deprecated
public void setFeatures(SerializerFeature... features) {
this.fastJsonConfig.setSerializerFeatures(features);
}
/**
* Get filters serialize filter [].
*
* @return the serialize filter []
* @see FastJsonConfig#getSerializeFilters()
* @deprecated
*/
@Deprecated
public SerializeFilter[] getFilters() {
return this.fastJsonConfig.getSerializeFilters();
}
/**
* Sets filters.
*
* @param filters the filters
* @see FastJsonConfig#setSerializeFilters(SerializeFilter...)
* @deprecated
*/
@Deprecated
public void setFilters(SerializeFilter... filters) {
this.fastJsonConfig.setSerializeFilters(filters);
}
/**
* Set renderedAttributes.
*
* @param renderedAttributes renderedAttributes
*/
public void setRenderedAttributes(Set renderedAttributes) {
this.renderedAttributes = renderedAttributes;
}
/**
* Check extractValueFromSingleKeyModel.
*
* @return extractValueFromSingleKeyModel
*/
public boolean isExtractValueFromSingleKeyModel() {
return extractValueFromSingleKeyModel;
}
/**
* Set extractValueFromSingleKeyModel.
*
* @param extractValueFromSingleKeyModel
*/
public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyModel) {
this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;
}
/**
* Set JSONP request parameter names. Each time a request has one of those
* parameters, the resulting JSON will be wrapped into a function named as
* specified by the JSONP request parameter value.
* The parameter names configured by default are "jsonp" and "callback".
*
* @see JSONP Wikipedia article
* @since 4.1
*/
public void setJsonpParameterNames(Set jsonpParameterNames) {
Assert.notEmpty(jsonpParameterNames, "jsonpParameterName cannot be empty");
this.jsonpParameterNames = jsonpParameterNames.toArray(new String[jsonpParameterNames.size()]);
}
private String getJsonpParameterValue(HttpServletRequest request) {
if (this.jsonpParameterNames != null) {
for (String name : this.jsonpParameterNames) {
String value = request.getParameter(name);
if (IOUtils.isValidJsonpQueryParam(value)) {
return value;
}
if (logger.isDebugEnabled()) {
logger.debug("Ignoring invalid jsonp parameter value: " + value);
}
}
}
return null;
}
@Override
protected void renderMergedOutputModel(Map model, //
HttpServletRequest request, //
HttpServletResponse response) throws Exception {
Object value = filterModel(model);
String jsonpParameterValue = getJsonpParameterValue(request);
if (jsonpParameterValue != null) {
JSONPObject jsonpObject = new JSONPObject(jsonpParameterValue);
jsonpObject.addParameter(value);
value = jsonpObject;
}
ByteArrayOutputStream outnew = new ByteArrayOutputStream();
int len = JSON.writeJSONStringWithFastJsonConfig(outnew, //
fastJsonConfig.getCharset(), //
value, //
fastJsonConfig.getSerializeConfig(), //
fastJsonConfig.getSerializeFilters(), //
fastJsonConfig.getDateFormat(), //
JSON.DEFAULT_GENERATE_FEATURE, //
fastJsonConfig.getSerializerFeatures());
if (this.updateContentLength) {
// Write content length (determined via byte array).
response.setContentLength(len);
}
// Flush byte array to servlet output stream.
ServletOutputStream out = response.getOutputStream();
outnew.writeTo(out);
outnew.close();
out.flush();
}
@Override
protected void prepareResponse(HttpServletRequest request, //
HttpServletResponse response) {
setResponseContentType(request, response);
response.setCharacterEncoding(fastJsonConfig.getCharset().name());
if (this.disableCaching) {
response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-Control", "no-cache, no-store, max-age=0");
response.addDateHeader("Expires", 1L);
}
}
/**
* Disables caching of the generated JSON.
*
* Default is {@code true}, which will prevent the client from caching the
* generated JSON.
*/
public void setDisableCaching(boolean disableCaching) {
this.disableCaching = disableCaching;
}
/**
* Whether to update the 'Content-Length' header of the response. When set
* to {@code true}, the response is buffered in order to determine the
* content length and set the 'Content-Length' header of the response.
*
* The default setting is {@code false}.
*/
public void setUpdateContentLength(boolean updateContentLength) {
this.updateContentLength = updateContentLength;
}
/**
* Filters out undesired attributes from the given model. The return value
* can be either another {@link Map}, or a single value object.
*
* Default implementation removes {@link BindingResult} instances and
* entries not included in the {@link #setRenderedAttributes(Set)
* renderedAttributes} property.
*
* @param model the model, as passed on to {@link #renderMergedOutputModel}
* @return the object to be rendered
*/
protected Object filterModel(Map model) {
Map result = new HashMap(model.size());
Set renderedAttributes = !CollectionUtils.isEmpty(this.renderedAttributes) ? //
this.renderedAttributes //
: model.keySet();
for (Map.Entry entry : model.entrySet()) {
if (!(entry.getValue() instanceof BindingResult)
&& renderedAttributes.contains(entry.getKey())) {
result.put(entry.getKey(), entry.getValue());
}
}
if (extractValueFromSingleKeyModel) {
if (result.size() == 1) {
for (Map.Entry entry : result.entrySet()) {
return entry.getValue();
}
}
}
return result;
}
@Override
protected void setResponseContentType(HttpServletRequest request, HttpServletResponse response) {
if (getJsonpParameterValue(request) != null) {
response.setContentType(DEFAULT_JSONP_CONTENT_TYPE);
} else {
super.setResponseContentType(request, response);
}
}
}