package com.alibaba.fastjson.support.jaxrs; import com.alibaba.fastjson.JSON; 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 javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Fastjson for JAX-RS Provider. * * @author smallnest * @author VictorZeng * @see MessageBodyReader * @see MessageBodyWriter * @since 1.2.9 */ @Provider @Consumes({MediaType.WILDCARD}) @Produces({MediaType.WILDCARD}) public class FastJsonProvider // implements MessageBodyReader<Object>, MessageBodyWriter<Object> { @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; /** * with fastJson config */ private FastJsonConfig fastJsonConfig = new FastJsonConfig(); /** * allow serialize/deserialize types in clazzes */ private Class<?>[] clazzes = null; /** * whether set PrettyFormat while exec WriteTo() */ private boolean pretty; /** * @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; } /** * Can serialize/deserialize all types. */ public FastJsonProvider() { } /** * Only serialize/deserialize all types in clazzes. */ public FastJsonProvider(Class<?>[] clazzes) { this.clazzes = clazzes; } /** * Set pretty format */ public FastJsonProvider setPretty(boolean p) { this.pretty = p; return this; } /** * Set charset. the default charset is UTF-8 */ @Deprecated public FastJsonProvider(String charset) { this.fastJsonConfig.setCharset(Charset.forName(charset)); } @Deprecated public Charset getCharset() { return this.fastJsonConfig.getCharset(); } @Deprecated public void setCharset(Charset charset) { this.fastJsonConfig.setCharset(charset); } @Deprecated public String getDateFormat() { return this.fastJsonConfig.getDateFormat(); } @Deprecated public void setDateFormat(String dateFormat) { this.fastJsonConfig.setDateFormat(dateFormat); } @Deprecated public SerializerFeature[] getFeatures() { return this.fastJsonConfig.getSerializerFeatures(); } @Deprecated public void setFeatures(SerializerFeature... features) { this.fastJsonConfig.setSerializerFeatures(features); } @Deprecated public SerializeFilter[] getFilters() { return this.fastJsonConfig.getSerializeFilters(); } @Deprecated public void setFilters(SerializeFilter... filters) { this.fastJsonConfig.setSerializeFilters(filters); } /** * Check whether a class can be serialized or deserialized. It can check * based on packages, annotations on entities or explicit classes. * * @param type class need to check * @return true if valid */ protected boolean isValidType(Class<?> type, Annotation[] classAnnotations) { if (type == null) return false; if (clazzes != null) { for (Class<?> cls : clazzes) { // must strictly equal. Don't check // inheritance if (cls == type) return true; } return false; } return true; } /** * Check media type like "application/json". * * @param mediaType media type * @return true if the media type is valid */ protected boolean hasMatchingMediaType(MediaType mediaType) { if (mediaType != null) { String subtype = mediaType.getSubtype(); return (("json".equalsIgnoreCase(subtype)) // || (subtype.endsWith("+json")) // || ("javascript".equals(subtype)) // || ("x-javascript".equals(subtype)) // || ("x-json".equals(subtype)) // || ("x-www-form-urlencoded".equalsIgnoreCase(subtype)) // || (subtype.endsWith("x-www-form-urlencoded"))); } return true; } /* * /********************************************************** /* Partial * MessageBodyWriter impl * /********************************************************** */ /** * Method that JAX-RS container calls to try to check whether given value * (of specified type) can be serialized by this provider. */ public boolean isWriteable(Class<?> type, // Type genericType, // Annotation[] annotations, // MediaType mediaType) { if (!hasMatchingMediaType(mediaType)) { return false; } return isValidType(type, annotations); } /** * Method that JAX-RS container calls to try to figure out serialized length * of given value. always return -1 to denote "not known". */ public long getSize(Object t, // Class<?> type, // Type genericType, // Annotation[] annotations, // MediaType mediaType) { return -1; } /** * Method that JAX-RS container calls to serialize given value. */ public void writeTo(Object obj, // Class<?> type, // Type genericType, // Annotation[] annotations, // MediaType mediaType, // MultivaluedMap<String, Object> httpHeaders, // OutputStream entityStream // ) throws IOException, WebApplicationException { SerializerFeature[] serializerFeatures = fastJsonConfig.getSerializerFeatures(); if (pretty) { if (serializerFeatures == null) serializerFeatures = new SerializerFeature[]{SerializerFeature.PrettyFormat}; else { List<SerializerFeature> featureList = new ArrayList<SerializerFeature>(Arrays .asList(serializerFeatures)); featureList.add(SerializerFeature.PrettyFormat); serializerFeatures = featureList.toArray(serializerFeatures); } fastJsonConfig.setSerializerFeatures(serializerFeatures); } int len = JSON.writeJSONString(entityStream, // fastJsonConfig.getCharset(), // obj, // fastJsonConfig.getSerializeConfig(), // fastJsonConfig.getSerializeFilters(), // fastJsonConfig.getDateFormat(), // JSON.DEFAULT_GENERATE_FEATURE, // fastJsonConfig.getSerializerFeatures()); // add Content-Length httpHeaders.add("Content-Length", String.valueOf(len)); entityStream.flush(); } /* * /********************************************************** /* * MessageBodyReader impl * /********************************************************** */ /** * Method that JAX-RS container calls to try to check whether values of * given type (and media type) can be deserialized by this provider. */ public boolean isReadable(Class<?> type, // Type genericType, // Annotation[] annotations, // MediaType mediaType) { if (!hasMatchingMediaType(mediaType)) { return false; } return isValidType(type, annotations); } /** * Method that JAX-RS container calls to deserialize given value. */ public Object readFrom(Class<Object> type, // Type genericType, // Annotation[] annotations, // MediaType mediaType, // MultivaluedMap<String, String> httpHeaders, // InputStream entityStream) throws IOException, WebApplicationException { return JSON.parseObject(entityStream, fastJsonConfig.getCharset(), genericType, fastJsonConfig.getFeatures()); } }