package com.github.approval.converters;
/*
* #%L
* approval-json
* %%
* Copyright (C) 2014 Nikolavp
* %%
* 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
*
* http://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.
* #L%
*/
import javax.annotation.Nonnull;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* A generic json converter that uses jackson for the serialization.
*
* @param <T>
* the type of objects that we are going to convert
*/
public final class JacksonJsonConverter<T> extends AbstractStringConverter<T> {
private static final JacksonJsonConverter SANE_DEFAULTS_INSTANCE = new JacksonJsonConverter(
mapperWithSaneDefaults());
private final ObjectMapper mapper;
private JacksonJsonConverter(ObjectMapper mapper) {
this.mapper = mapper;
}
/**
* Gets a converter with sane defaults from jackson. The sane defaults are
* the following:
*
* <ul>
* <li>format/indent the output</li>
* <li>write dates in a human readable format</li>
* <li>sort properties alphabetically</li>
* <li>don't include properties that were null</li>
* </ul>
*
* @param <T>
* the type of objects that will be converted
* @return a converter with sane defaults
*/
public static <T> JacksonJsonConverter<T> getInstanceWithSaneDefaults() {
// noinspection unchecked
return SANE_DEFAULTS_INSTANCE;
}
/**
* Gets a converter for the specified object mapper instance.
*
* @param objectMapper
* the object mapper that will be used
* @param <T>
* the type of objects that will be converted
* @return a converter for the specified mapper instance
*/
public static <T> JacksonJsonConverter<T> getInstanceWithObjectMapper(ObjectMapper objectMapper) {
return new JacksonJsonConverter<T>(objectMapper);
}
/**
* Gets a new jackson mapper applying our sane defaults on top. The sane
* defaults are the following:
*
* <ul>
* <li>format/indent the output</li>
* <li>write dates in a human readable format</li>
* <li>sort properties alphabetically</li>
* <li>don't include properties that were null</li>
* </ul>
*
* <p>This method allows you to change the mapper in your own way, adding mixins and what not. The change
* was made by a request from https://github.com/nikolavp/approval/pull/23</p>
*
* @return a jackson object mapper with sane defaults
*/
public static ObjectMapper mapperWithSaneDefaults() {
return new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
}
@Nonnull
@Override
protected String getStringForm(T entity) {
try {
return mapper.writeValueAsString(entity);
} catch (JsonProcessingException e) {
throw new AssertionError("Could not convert " + entity.getClass() + "object", e);
}
}
}