001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 *     http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014package org.gbif.ws.json;
015
016import org.gbif.api.ws.mixin.Mixins;
017
018import com.fasterxml.jackson.annotation.JsonInclude;
019import com.fasterxml.jackson.databind.DeserializationFeature;
020import com.fasterxml.jackson.databind.ObjectMapper;
021import com.fasterxml.jackson.databind.SerializationFeature;
022import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
023import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
024import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
025
026public final class JacksonJsonObjectMapperProvider {
027
028  private JacksonJsonObjectMapperProvider() {}
029
030  /** Creates an ObjectMapper with the default configuration.*/
031  public static ObjectMapper getDefaultObjectMapper() {
032    final ObjectMapper objectMapper = new ObjectMapper();
033    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
034    // determines whether encountering of unknown properties (ones that do not map to a property,
035    // and there is no
036    // "any setter" or handler that can handle it) should result in a failure (throwing a
037    // JsonMappingException) or not.
038    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
039
040    objectMapper.disable(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES);
041
042    objectMapper.disable(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES);
043
044    // Enforce use of ISO-8601 format dates (http://wiki.fasterxml.com/JacksonFAQDateHandling)
045    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
046
047    return objectMapper;
048  }
049
050  /** Creates an ObjectMapper with the default GBIF Mixins. */
051  public static ObjectMapper getObjectMapper() {
052    ObjectMapper objectMapper = getDefaultObjectMapper();
053
054    Mixins.getPredefinedMixins().forEach(objectMapper::addMixIn);
055
056    return objectMapper;
057  }
058
059  /**
060   * Creates an ObjectMapper that supports builders having a build method called "build" and without prefixes on methods.
061   */
062  public static ObjectMapper getObjectMapperWithBuilderSupport() {
063    return addBuilderSupport(getObjectMapper());
064  }
065
066  public static ObjectMapper addBuilderSupport(ObjectMapper objectMapper) {
067    objectMapper.setAnnotationIntrospector(
068        new JacksonAnnotationIntrospector() {
069          @Override
070          public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
071            if (ac.hasAnnotation(
072                JsonPOJOBuilder.class)) { // If no annotation present use default as empty prefix
073              return super.findPOJOBuilderConfig(ac);
074            }
075            return new JsonPOJOBuilder.Value("build", "");
076          }
077        });
078    return objectMapper;
079  }
080}