/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.jackson;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.micronaut.context.annotation.ConfigurationProperties;
import io.micronaut.core.annotation.Experimental;
import io.micronaut.core.annotation.TypeHint;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.ArgumentUtils;
import io.micronaut.core.util.ArrayUtils;
import io.micronaut.core.util.CollectionUtils;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.*;
Configuration for the Jackson JSON parser.
Author: Graeme Rocher Since: 1.0
/**
* Configuration for the Jackson JSON parser.
*
* @author Graeme Rocher
* @since 1.0
*/
@ConfigurationProperties("jackson")
@TypeHint(
value = {
PropertyNamingStrategy.UpperCamelCaseStrategy.class,
ArrayList.class,
LinkedHashMap.class,
HashSet.class
})
public class JacksonConfiguration {
The default array size threshold value.
/**
* The default array size threshold value.
*/
@SuppressWarnings("WeakerAccess")
public static final int DEFAULT_ARRAYSIZETHRESHOLD = 100;
The property used to enable module scan.
/**
* The property used to enable module scan.
*/
public static final String PROPERTY_MODULE_SCAN = "jackson.module-scan";
The property used to enable bean introspection.
/**
* The property used to enable bean introspection.
*/
public static final String PROPERTY_USE_BEAN_INTROSPECTION = "jackson.bean-introspection-module";
private boolean moduleScan = true;
private boolean beanIntrospectionModule = false;
private String dateFormat;
private Locale locale;
private TimeZone timeZone;
private int arraySizeThreshold = DEFAULT_ARRAYSIZETHRESHOLD;
private Map<SerializationFeature, Boolean> serialization = Collections.emptyMap();
private Map<DeserializationFeature, Boolean> deserialization = Collections.emptyMap();
private Map<MapperFeature, Boolean> mapper = Collections.emptyMap();
private Map<JsonParser.Feature, Boolean> parser = Collections.emptyMap();
private Map<JsonGenerator.Feature, Boolean> generator = Collections.emptyMap();
private JsonInclude.Include serializationInclusion = JsonInclude.Include.NON_EMPTY;
private ObjectMapper.DefaultTyping defaultTyping = null;
private PropertyNamingStrategy propertyNamingStrategy = null;
Whether the BeanIntrospection
should be used for reflection free object serialialization/deserialialization. Returns: True if it should
/**
* Whether the {@link io.micronaut.core.beans.BeanIntrospection} should be used for reflection free object serialialization/deserialialization.
* @return True if it should
*/
@Experimental
public boolean isBeanIntrospectionModule() {
return beanIntrospectionModule;
}
Whether the BeanIntrospection
should be used for reflection free object serialialization/deserialialization. Params: - beanIntrospectionModule – True if it should
/**
* Whether the {@link io.micronaut.core.beans.BeanIntrospection} should be used for reflection free object serialialization/deserialialization.
*
* @param beanIntrospectionModule True if it should
*/
@Experimental
public void setBeanIntrospectionModule(boolean beanIntrospectionModule) {
this.beanIntrospectionModule = beanIntrospectionModule;
}
Whether Jackson modules should be scanned for.
Returns: True if module scanning is enabled
/**
* Whether Jackson modules should be scanned for.
*
* @return True if module scanning is enabled
*/
public boolean isModuleScan() {
return moduleScan;
}
Sets whether to scan for modules or not (defaults to true).
Params: - moduleScan – True if module scan should be enabled
/**
* Sets whether to scan for modules or not (defaults to true).
* @param moduleScan True if module scan should be enabled
*/
public void setModuleScan(boolean moduleScan) {
this.moduleScan = moduleScan;
}
Returns: The default serialization inclusion settings
/**
* @return The default serialization inclusion settings
*/
public JsonInclude.Include getSerializationInclusion() {
return serializationInclusion;
}
Returns: The global defaultTyping using for Polymorphic handling
/**
* @return The global defaultTyping using for Polymorphic handling
*/
public ObjectMapper.DefaultTyping getDefaultTyping() {
return defaultTyping;
}
Returns: The default locale to use
/**
* @return The default locale to use
*/
public Locale getLocale() {
return locale;
}
Returns: The default time zone to use
/**
* @return The default time zone to use
*/
public TimeZone getTimeZone() {
return timeZone;
}
Returns: The date format to use for dates
/**
* @return The date format to use for dates
*/
public String getDateFormat() {
return dateFormat;
}
Returns: The serialization settings
/**
* @return The serialization settings
*/
public Map<SerializationFeature, Boolean> getSerializationSettings() {
return serialization;
}
Returns: The deserialization settings
/**
* @return The deserialization settings
*/
public Map<DeserializationFeature, Boolean> getDeserializationSettings() {
return deserialization;
}
Returns: Settings for the object mapper
/**
* @return Settings for the object mapper
*/
public Map<MapperFeature, Boolean> getMapperSettings() {
return mapper;
}
Returns: Settings for the parser
/**
* @return Settings for the parser
*/
public Map<JsonParser.Feature, Boolean> getParserSettings() {
return parser;
}
Returns: Settings for the generator
/**
* @return Settings for the generator
*/
public Map<JsonGenerator.Feature, Boolean> getGeneratorSettings() {
return generator;
}
Returns: The array size threshold to use when using Jackson for data binding
/**
* @return The array size threshold to use when using Jackson for data binding
*/
public int getArraySizeThreshold() {
return arraySizeThreshold;
}
Returns: The property naming strategy
/**
* @return The property naming strategy
*/
public PropertyNamingStrategy getPropertyNamingStrategy() {
return propertyNamingStrategy;
}
Sets the default date format to use.
Params: - dateFormat – The date format
/**
* Sets the default date format to use.
* @param dateFormat The date format
*/
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
Sets the locale to use.
Params: - locale – The locale
/**
* Sets the locale to use.
* @param locale The locale
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
Sets the timezone to use.
Params: - timeZone – The timezone
/**
* Sets the timezone to use.
* @param timeZone The timezone
*/
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
Sets the array size threshold for data binding. Default value (100). Params: - arraySizeThreshold – The array size threshold
/**
* Sets the array size threshold for data binding. Default value ({@value #DEFAULT_ARRAYSIZETHRESHOLD}).
* @param arraySizeThreshold The array size threshold
*/
public void setArraySizeThreshold(int arraySizeThreshold) {
this.arraySizeThreshold = arraySizeThreshold;
}
Sets the serialization features to use.
Params: - serialization – The serialization features.
/**
* Sets the serialization features to use.
* @param serialization The serialization features.
*/
public void setSerialization(Map<SerializationFeature, Boolean> serialization) {
if (CollectionUtils.isNotEmpty(serialization)) {
this.serialization = serialization;
}
}
Sets the deserialization features to use.
Params: - deserialization – The deserialiation features.
/**
* Sets the deserialization features to use.
* @param deserialization The deserialiation features.
*/
public void setDeserialization(Map<DeserializationFeature, Boolean> deserialization) {
if (CollectionUtils.isNotEmpty(deserialization)) {
this.deserialization = deserialization;
}
}
Sets the object mapper features to use.
Params: - mapper – The object mapper features
/**
* Sets the object mapper features to use.
* @param mapper The object mapper features
*/
public void setMapper(Map<MapperFeature, Boolean> mapper) {
if (CollectionUtils.isNotEmpty(mapper)) {
this.mapper = mapper;
}
}
Sets the parser features to use.
Params: - parser – The parser features
/**
* Sets the parser features to use.
* @param parser The parser features
*/
public void setParser(Map<JsonParser.Feature, Boolean> parser) {
if (CollectionUtils.isNotEmpty(parser)) {
this.parser = parser;
}
}
Sets the generator features to use.
Params: - generator – The generator features
/**
* Sets the generator features to use.
* @param generator The generator features
*/
public void setGenerator(Map<JsonGenerator.Feature, Boolean> generator) {
if (CollectionUtils.isNotEmpty(generator)) {
this.generator = generator;
}
}
Sets the serialization inclusion mode.
Params: - serializationInclusion – The serialization inclusion mode
/**
* Sets the serialization inclusion mode.
*
* @param serializationInclusion The serialization inclusion mode
*/
public void setSerializationInclusion(JsonInclude.Include serializationInclusion) {
if (serializationInclusion != null) {
this.serializationInclusion = serializationInclusion;
}
}
Sets the global defaultTyping using for Polymorphic handling.
Params: - defaultTyping – The defaultTyping
/**
* Sets the global defaultTyping using for Polymorphic handling.
*
* @param defaultTyping The defaultTyping
*/
public void setDefaultTyping(ObjectMapper.DefaultTyping defaultTyping) {
this.defaultTyping = defaultTyping;
}
Sets the property naming strategy.
Params: - propertyNamingStrategy – The property naming strategy
/**
* Sets the property naming strategy.
*
* @param propertyNamingStrategy The property naming strategy
*/
public void setPropertyNamingStrategy(PropertyNamingStrategy propertyNamingStrategy) {
this.propertyNamingStrategy = propertyNamingStrategy;
}
Constructors a JavaType for the given argument and type factory.
Params: - type – The type
- typeFactory – The type factory
Type parameters: - <T> – The generic type
Returns: The JavaType
/**
* Constructors a JavaType for the given argument and type factory.
* @param type The type
* @param typeFactory The type factory
* @param <T> The generic type
* @return The JavaType
*/
public static <T> JavaType constructType(@NonNull Argument<T> type, @NonNull TypeFactory typeFactory) {
ArgumentUtils.requireNonNull("type", type);
ArgumentUtils.requireNonNull("typeFactory", typeFactory);
Map<String, Argument<?>> typeVariables = type.getTypeVariables();
JavaType[] objects = toJavaTypeArray(typeFactory, typeVariables);
final Class<T> rawType = type.getType();
if (ArrayUtils.isNotEmpty(objects)) {
final JavaType javaType = typeFactory.constructType(
rawType
);
if (javaType.isCollectionLikeType()) {
return typeFactory.constructCollectionLikeType(
rawType,
objects[0]
);
} else if (javaType.isMapLikeType()) {
return typeFactory.constructMapLikeType(
rawType,
objects[0],
objects[1]
);
} else if (javaType.isReferenceType()) {
return typeFactory.constructReferenceType(rawType, objects[0]);
}
return typeFactory.constructParametricType(rawType, objects);
} else {
return typeFactory.constructType(
rawType
);
}
}
private static JavaType[] toJavaTypeArray(TypeFactory typeFactory, Map<String, Argument<?>> typeVariables) {
List<JavaType> javaTypes = new ArrayList<>();
for (Argument<?> argument : typeVariables.values()) {
if (argument.hasTypeVariables()) {
javaTypes.add(typeFactory.constructParametricType(argument.getType(), toJavaTypeArray(typeFactory, argument.getTypeVariables())));
} else {
javaTypes.add(typeFactory.constructType(argument.getType()));
}
}
return javaTypes.toArray(new JavaType[0]);
}
}