Jackson
Implementierung eines TypeIdResolver
Der folgende Code-Ausschnitt zeigt die Implementierung eines TypeIdResolver.
public class MyTypeIdResolver implements TypeIdResolver
{
// ============================== [Fields] ==============================
// -------------------- [Private Fields] --------------------
private JavaType baseType;
// ============================== [Getter/Setter] ==============================
// -------------------- [Public Getter/Setter] --------------------
@Override
public Id getMechanism()
{
return Id.CUSTOM;
}
// ============================== [Methods] ==============================
// -------------------- [Public Methods] --------------------
@Override
public void init(JavaType baseType)
{
this.baseType = baseType;
}
@Override
public String idFromValue(Object value)
{
return idFromValueAndType(value, value.getClass());
}
@Override
public String idFromValueAndType(Object value, Class<?> suggestedType)
{
return suggestedType.getName();
}
@Override
public String idFromBaseType()
{
return idFromValueAndType(null, this.baseType.getClass());
}
@Override
public JavaType typeFromId(String id)
{
Class<?> resolvedClass = null;
try
{
resolvedClass = ClassUtil.findClass(id);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
return TypeFactory.defaultInstance().constructSpecializedType(this.baseType, resolvedClass);
}
}
Die entsprechende (Basis-)Klasse muss folgende Annotations spezifizieren.
@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonTypeIdResolver(MyTypeIdResolver.class)
public abstract class AnalysisIntervalViewModel implements ViewModel
{
...
}
Implementierung eines Custom-Serializers
Der folgende Code-Ausschnitt zeigt die Implementierung eines Custom-Serializers. Die Registrierung eines Serializers erfolgt über einen Context Resolver (siehe unten).
public class AppZonedDateTimeSerializer extends JsonSerializer<AppZonedDateTime>
{
// ============================== [Methods] ==============================
// -------------------- [Public Methods] --------------------
/*
* (non-Javadoc)
*
* @see com.fasterxml.jackson.databind.JsonSerializer#serialize(java.lang.Object,
* com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
*/
@Override
public void serialize(AppZonedDateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException
{
jgen.writeStartObject();
jgen.writeStringField("isoDateTime", value.getIsoDateTime());
jgen.writeStringField("timeZoneIdTzDb", value.getTimeZoneIdTzDb());
jgen.writeEndObject();
}
}
Implementierung eines Custom-Deserializers
Der folgende Code-Ausschnitt zeigt die Implementierung eines Custom-Deserializers. Die Registrierung eines Deserializers erfolgt über einen Context Resolver (siehe unten).
public class AppZonedDateTimeDeserializer extends JsonDeserializer<AppZonedDateTime>
{
// ============================== [Methods] ==============================
// -------------------- [Public Methods] --------------------
/*
* (non-Javadoc)
*
* @see
* com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser
* , com.fasterxml.jackson.databind.DeserializationContext)
*/
@Override
public AppZonedDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
JsonNode node = jp.getCodec().readTree(jp);
String isoDateTime = node.get("isoDateTime").asText();
String timeZone = node.get("timeZoneIdTzDb").asText();
return new AppZonedDateTime("N/A", isoDateTime, timeZone);
}
Implementierung eines ContextResolver bzw. Object Mapper Provider
Mit Hilfe eines Context Resolvers bzw. Object Mapper Provider ist es möglich Serializer und Deserializer im Jackson Framework zu registrieren.
@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper>
{
// ============================== [Fields] ==============================
// -------------------- [Private Fields] --------------------
private final ObjectMapper defaultObjectMapper;
// ============================== [Construction / Destruction] ==============================
// -------------------- [Public Construction / Destruction] --------------------
public MyObjectMapperProvider()
{
SimpleModule module = new SimpleModule();
module.addDeserializer(AppZonedDateTime.class, new AppZonedDateTimeDeserializer());
module.addSerializer(AppZonedDateTime.class, new AppZonedDateTimeSerializer());
this.defaultObjectMapper = new ObjectMapper();
this.defaultObjectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
// this.defaultObjectMapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
// this.defaultObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
this.defaultObjectMapper.registerModule(module);
}
// ============================== [Getter/Setter] ==============================
// -------------------- [Public Getter/Setter] --------------------
@Override
public ObjectMapper getContext(Class<?> type)
{
return defaultObjectMapper;
}
}
@JsonTypeInfo und @JsonSubTypes
An Beispielen soll die Verwendung der Annotations @JsonTypeInfo und @JsonSubTypes veranschaulicht werden.
Der folgende Code-Ausschnitt wurde verwendet, JSON mit abgeleiteten Datentypen zwischen Java (Jersey inkl. Jackson) und .NET (WCF) auszutauschen.
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "__type")
@JsonSubTypes({ @Type(value = DayViewModel.class, name = "DayStatic:#Servicetrace.Reporting"),
@Type(value = WeekViewModel.class, name = "WeekStatic:#Servicetrace.Reporting"),
@Type(value = MonthViewModel.class, name = "MonthStatic:#Servicetrace.Reporting"),
@Type(value = QuarterViewModel.class, name = "QuarterStatic:#Servicetrace.Reporting"),
@Type(value = YearViewModel.class, name = "YearStatic:#Servicetrace.Reporting"),
@Type(value = CustomIntervalViewModel.class, name = "CustomStatic:#Servicetrace.Reporting"),
@Type(value = TodayViewModel.class, name = "TodayDynamic:#Servicetrace.Reporting"),
@Type(value = YesterdayViewModel.class, name = "YesterdayDynamic:#Servicetrace.Reporting"),
@Type(value = CurrentWeekViewModel.class, name = "CurrentWeekDynamic:#Servicetrace.Reporting"),
@Type(value = LastWeekViewModel.class, name = "LastWeekDynamic:#Servicetrace.Reporting"),
@Type(value = CurrentMonthViewModel.class, name = "CurrentMonthDynamic:#Servicetrace.Reporting"),
@Type(value = LastMonthViewModel.class, name = "LastMonthDynamic:#Servicetrace.Reporting"),
@Type(value = CurrentQuarterViewModel.class, name = "CurrentQuarterDynamic:#Servicetrace.Reporting"),
@Type(value = LastQuarterViewModel.class, name = "LastQuarterDynamic:#Servicetrace.Reporting"),
@Type(value = CurrentYearViewModel.class, name = "CurrentYearDynamic:#Servicetrace.Reporting"),
@Type(value = LastYearViewModel.class, name = "LastYearDynamic:#Servicetrace.Reporting"),
@Type(value = LastHoursViewModel.class, name = "LastHoursDynamic:#Servicetrace.Reporting") })
public abstract class AnalysisIntervalViewModel implements ViewModel
{
...
}
Der folgende Code-Ausschnitt wurde verwendet, JSON mit abgeleiteten Datentypen zwischen einem Java Client und Java Server (jeweils Jersey inkl. Jackson) auszutauschen.
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "@class")
public abstract class AnalysisConfigViewModel implements ViewModel
{
...
}