com.geotab.model.serialization.ApiJsonSerializer Maven / Gradle / Ivy
/*
*
* 2020 Copyright (C) Geotab Inc. All rights reserved.
*/
package com.geotab.model.serialization;
import static com.geotab.model.serialization.filter.FaultDataFilterProvider.FAULT_DATA_FILTER;
import static com.geotab.model.serialization.filter.SensorDataFilterProvider.SENSOR_DATA_FILTER;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.geotab.model.enumeration.DbUnavailableState;
import com.geotab.model.enumeration.DevicePlan;
import com.geotab.model.enumeration.DeviceType;
import com.geotab.model.enumeration.DiagnosticType;
import com.geotab.model.enumeration.DtcClass;
import com.geotab.model.enumeration.FaultLampState;
import com.geotab.model.enumeration.FaultResetMode;
import com.geotab.model.enumeration.FaultState;
import com.geotab.model.enumeration.HosRuleSet;
import com.geotab.model.enumeration.MessageContentType;
import com.geotab.model.enumeration.SecurityIdentifier;
import com.geotab.model.enumeration.UserAuthenticationType;
import com.geotab.model.enumeration.ValidLoggingPeriod;
import com.geotab.model.enumeration.VehicleFeatureCategory;
import com.geotab.model.serialization.filter.FaultDataFilterProvider;
import com.geotab.model.serialization.filter.SensorDataFilterProvider;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicReference;
/**
* Json serializer singleton which configures and keeps a single reference of the {@link
* ObjectMapper} to be used by the {@link com.geotab.api.GeotabApi}.
*/
public final class ApiJsonSerializer {
private static class InstanceHolder {
private static final ApiJsonSerializer INSTANCE = new ApiJsonSerializer();
}
private final AtomicReference objectMapperReference = new AtomicReference<>();
private ApiJsonSerializer() {
this.objectMapperReference.set(buildDefaultObjectMapper());
}
public static ApiJsonSerializer getInstance() {
return InstanceHolder.INSTANCE;
}
/**
* Build default configuration for {@link ObjectMapper}.
*
* @return The {@link ObjectMapper}.
*/
public ObjectMapper buildDefaultObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.setSerializationInclusion(Include.NON_NULL);
registerLongSerializationModule(objectMapper);
registerTimeSerializationModule(objectMapper);
registerCustomSerializationModule(objectMapper);
registerEnumsSerializationModule(objectMapper);
registerFilterProvider(objectMapper);
return objectMapper;
}
public void registerLongSerializationModule(ObjectMapper objectMapper) {
objectMapper.registerModule(new SimpleModule("api-long-serialization-module")
.addSerializer(long.class, new LongSerializer())
.addSerializer(Long.class, new LongSerializer())
.addDeserializer(long.class, new LongDeserializer())
.addDeserializer(Long.class, new LongDeserializer())
);
}
public void registerTimeSerializationModule(ObjectMapper objectMapper) {
objectMapper.registerModule(new SimpleModule("api-time-serialization-module")
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer())
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer())
.addSerializer(Duration.class, new DurationSerializer())
.addDeserializer(Duration.class, new DurationDeserializer())
);
}
public void registerCustomSerializationModule(ObjectMapper objectMapper) {
objectMapper.registerModule(new SimpleModule("api-custom-serialization-module")
.setSerializerModifier(new ApiCustomSerializerModifier())
.setDeserializerModifier(new ApiCustomDeserializerModifier())
);
}
public void registerEnumsSerializationModule(ObjectMapper objectMapper) {
objectMapper.registerModule(new SimpleModule("api-enums-serialization-module")
.addDeserializer(DbUnavailableState.class, new DbUnavailableStateDeserializer())
.addDeserializer(DevicePlan.class, new DevicePlanDeserializer())
.addDeserializer(DeviceType.class, new DeviceTypeDeserializer())
.addDeserializer(DiagnosticType.class, new DiagnosticTypeDeserializer())
.addDeserializer(DtcClass.class, new DtcClassDeserializer())
.addDeserializer(FaultLampState.class, new FaultLampStateDeserializer())
.addDeserializer(FaultResetMode.class, new FaultResetModeDeserializer())
.addDeserializer(FaultState.class, new FaultStateDeserializer())
.addDeserializer(HosRuleSet.class, new HosRuleSetDeserializer())
.addDeserializer(MessageContentType.class, new MessageContentTypeDeserializer())
.addDeserializer(SecurityIdentifier.class, new SecurityIdentifierDeserializer())
.addDeserializer(UserAuthenticationType.class, new UserAuthenticationTypeDeserializer())
.addDeserializer(ValidLoggingPeriod.class, new ValidLoggingPeriodDeserializer())
.addDeserializer(VehicleFeatureCategory.class, new VehicleFeatureCategoryDeserializer())
);
}
public void registerFilterProvider(ObjectMapper objectMapper) {
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter(FAULT_DATA_FILTER, new FaultDataFilterProvider());
filterProvider.addFilter(SENSOR_DATA_FILTER, new SensorDataFilterProvider());
objectMapper.setFilterProvider(filterProvider);
}
/**
* !!! Use with caution !!!
*
* This method represents an extension point for the json serialization. It's recommended that
* the API uses the default serialization config, but in case custom serialization config is
* needed, then this method can be used.
*
*
Recommendation is to start from {@link #buildDefaultObjectMapper()},add
* custom config and then call {@link #withCustomObjectMapper(ObjectMapper)}()}, before
* instantiating {@link com.geotab.api.GeotabApi}.
*
* @param objectMapper The custom {@link ObjectMapper}.
*/
public void withCustomObjectMapper(ObjectMapper objectMapper) {
if (objectMapper == null) {
throw new IllegalArgumentException("ObjectMapper can not be null !");
}
this.objectMapperReference.set(objectMapper);
}
/**
* Get the configured {@link ObjectMapper}.
*
* @return The {@link ObjectMapper}.
*/
public ObjectMapper getObjectMapper() {
return objectMapperReference.get();
}
}