package ameba.message.jackson.internal; import ameba.core.Application; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.introspect.*; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.datatype.guava.GuavaModule; import com.fasterxml.jackson.jaxrs.cfg.ObjectWriterInjector; import org.glassfish.jersey.internal.util.ReflectionHelper; import org.glassfish.jersey.message.filtering.spi.ObjectProvider; import javax.inject.Provider; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; /** * <p>JacksonUtils class.</p> * * @author icode * @since 0.1.6e */ public class JacksonUtils { private JacksonUtils() { } /** * <p>configFilterIntrospector.</p> * * @param mapper a {@link com.fasterxml.jackson.databind.ObjectMapper} object. * @return a {@link com.fasterxml.jackson.databind.ObjectMapper} object. */ public static ObjectMapper configFilterIntrospector(final ObjectMapper mapper) { final AnnotationIntrospector customIntrospector = mapper.getSerializationConfig().getAnnotationIntrospector(); // Set the custom (user) introspector to be the primary one. return mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(customIntrospector, new JacksonAnnotationIntrospector() { @Override public Object findFilterId(final Annotated a) { final Object filterId = super.findFilterId(a); if (filterId != null) { return filterId; } if (a instanceof AnnotatedMethod) { final Method method = ((AnnotatedMethod) a).getAnnotated(); // Interested only in getters - trying to obtain "field" name from them. if (ReflectionHelper.isGetter(method)) { return ReflectionHelper.getPropertyName(method); } } if (a instanceof AnnotatedField || a instanceof AnnotatedClass) { return a.getName(); } return null; } })); } /** * <p>setObjectWriterInjector.</p> * * @param provider a {@link javax.inject.Provider} object. * @param genericType a {@link java.lang.reflect.Type} object. * @param annotations an array of {@link java.lang.annotation.Annotation} objects. * @throws java.io.IOException if any. */ public static void setObjectWriterInjector(Provider<ObjectProvider<FilterProvider>> provider, final Type genericType, final Annotation[] annotations) throws IOException { final FilterProvider filterProvider = provider.get().getFilteringObject(genericType, true, annotations); if (filterProvider != null) { ObjectWriterInjector.set(new FilteringObjectWriterModifier(filterProvider, ObjectWriterInjector.getAndClear())); } } /** * <p>configureMapper.</p> * * @param mapper a {@link com.fasterxml.jackson.databind.ObjectMapper} object. * @param mode App mode */ public static void configureMapper(ObjectMapper mapper, Application.Mode mode) { mapper.registerModule(new GuavaModule()); mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY) .enable(SerializationFeature.WRITE_ENUMS_USING_INDEX) .disable( SerializationFeature.WRITE_NULL_MAP_VALUES, SerializationFeature.FAIL_ON_EMPTY_BEANS ); if (!mode.isDev()) { mapper.disable( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES ); } } /** * <p>configureGenerator.</p> * * @param uriInfo a {@link javax.ws.rs.core.UriInfo} object. * @param generator a {@link com.fasterxml.jackson.core.JsonGenerator} object. * @param isDev a boolean. */ public static void configureGenerator(UriInfo uriInfo, JsonGenerator generator, boolean isDev) { MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); String pretty = params.getFirst("pretty"); if ("false".equalsIgnoreCase(pretty)) { generator.setPrettyPrinter(null); } else if (pretty != null && !"false".equalsIgnoreCase(pretty) || isDev) { generator.useDefaultPrettyPrinter(); } String unicode = params.getFirst("unicode"); if (unicode != null && !"false".equalsIgnoreCase(unicode)) { generator.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); } } }