All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.colobu.fastjson.FastJsonProvider Maven / Gradle / Ivy

The newest version!
package com.colobu.fastjson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.*;

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.util.Arrays;
import java.util.List;

/**
 * JAX-RS Provider for fastjson.
 * 
 * @author smallnest
 *
 */
@Provider
public class FastJsonProvider implements MessageBodyReader, MessageBodyWriter {
	private boolean annotated = false;
	private String[] scanpackages = null;
	private Class[] clazzes = null;

	protected boolean pretty;

	protected FastJsonConfig fastJsonConfig = new FastJsonConfig(new SerializeConfig(), null, null, new ParserConfig(), null);

	/**
	 * Can serialize/deserialize all types.
	 */
	public FastJsonProvider() {

	}

	/**
	 * Only serialize/deserialize all types annotated with {@link com.colobu.fastjson.FastJsonType}.
	 */
	public FastJsonProvider(boolean annotated) {
		this.annotated = annotated;
	}
	
	/**
	 * Only serialize/deserialize all types in scanpackages.
	 */
	public FastJsonProvider(String[] scanpackages) {
		this.scanpackages = scanpackages;
	}

	/**
	 * Only serialize/deserialize all types in scanpackages.
	 */
	public FastJsonProvider(String[] scanpackages, boolean annotated) {
		this.scanpackages = scanpackages;
		this.annotated = annotated;	
	}
	
	/**
	 * Only serialize/deserialize all types in clazzes.
	 */
	public FastJsonProvider(Class[] clazzes) {
		this.clazzes = clazzes;
	}

	/**
	 * Init this provider with more fastjson configurations.
	 * @param fastJsonConfig fastjson config
	 */
	public FastJsonProvider init(FastJsonConfig fastJsonConfig) {
		this.fastJsonConfig = fastJsonConfig;
		return this;
	}


	// Set pretty format
	public FastJsonProvider setPretty(boolean p) {
		this.pretty = p;
		return this;
	}
	
	/**
	 * 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 (annotated) {
			return checkAnnotation(type);			
		} else if (scanpackages != null) {
			String classPackage = type.getPackage().getName();
			for (String pkg : scanpackages) {
				if (classPackage.startsWith(pkg)) {
					if (annotated) {
						return checkAnnotation(type);		
					} else
						return true;
				}
					
			}

			return false;
		} else if (clazzes != null) {
			for (Class cls : clazzes) { // must strictly equal. Don't check
											// inheritance
				if (cls == type)
					return true;
			}

			return false;
		}

		return true;
	}

	private boolean checkAnnotation(Class type) {
		Annotation[] annotations = type.getAnnotations();
		for (Annotation annotation : annotations) {
			if (annotation instanceof FastJsonType) {
				return true;
			}
		}
		
		return false;
	}

	/**
	 * 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);
		}
		return true;
	}

	public String toJSONString(Object object, SerializeFilter filter, SerializerFeature[] features) {
        SerializeWriter out = new SerializeWriter();

        try {
            JSONSerializer serializer = new JSONSerializer(out, fastJsonConfig.serializeConfig);
            if (features != null) {
            	for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
                    serializer.config(feature, true);
                }
            }
            
            if (filter != null) {
                if (filter instanceof PropertyPreFilter) {
                    serializer.getPropertyPreFilters().add((PropertyPreFilter) filter);
                }

                if (filter instanceof NameFilter) {
                    serializer.getNameFilters().add((NameFilter) filter);
                }

                if (filter instanceof ValueFilter) {
                    serializer.getValueFilters().add((ValueFilter) filter);
                }

                if (filter instanceof PropertyFilter) {
                    serializer.getPropertyFilters().add((PropertyFilter) filter);
                }

                if (filter instanceof BeforeFilter) {
                    serializer.getBeforeFilters().add((BeforeFilter) filter);
                }
                
                if (filter instanceof AfterFilter) {
                    serializer.getAfterFilters().add((AfterFilter) filter);
                }
            }

            serializer.write(object);

            return out.toString();
        } finally {
            out.close();
        }
    }

	/*
	 * /********************************************************** /* 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 t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders,
			OutputStream entityStream) throws IOException, WebApplicationException {
		SerializeFilter filter = null;

        if(pretty) {
			if (fastJsonConfig.serializerFeatures == null)
				fastJsonConfig.serializerFeatures = new  SerializerFeature[]{SerializerFeature.PrettyFormat};
            else {
                List serializerFeatures = Arrays.asList(fastJsonConfig.serializerFeatures);
                serializerFeatures.add(SerializerFeature.PrettyFormat);
                fastJsonConfig.serializerFeatures = serializerFeatures.toArray(new SerializerFeature[]{});
            }
		}

		if (fastJsonConfig.serializeFilters != null)
			filter = fastJsonConfig.serializeFilters.get(type);
		String jsonStr = toJSONString(t, filter, fastJsonConfig.serializerFeatures);
		if (jsonStr != null)
			entityStream.write(jsonStr.getBytes());
	}

	/*
	 * /********************************************************** /*
	 * 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 type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders,
			InputStream entityStream) throws IOException, WebApplicationException {
		String input = null;
		try {
			input = IOUtils.inputStreamToString(entityStream);
		} catch (Exception e) {
			
		}
		if (input == null) {
            return null;
        }
		if (fastJsonConfig.features == null)
			return JSON.parseObject(input, type, fastJsonConfig.parserConfig, JSON.DEFAULT_PARSER_FEATURE);
		else
			return JSON.parseObject(input, type, fastJsonConfig.parserConfig, JSON.DEFAULT_PARSER_FEATURE, fastJsonConfig.features);
	}

}