fix(serialize-databind): add (optional) support for hierarchical TypeAdapters
This commit is contained in:
parent
2512ff4834
commit
25259ba3b7
|
@ -15,31 +15,32 @@ public class ObjectMapper {
|
|||
private final ConcurrentMap<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<>();
|
||||
private final List<TypeAdapterFactory> factories = new ArrayList<>();
|
||||
private final Map<TypeToken<?>, TypeAdapter<?>> explicitAdapters = new ConcurrentHashMap<>();
|
||||
private final Map<TypeToken<?>, TypeAdapter<?>> hierarchyAdapters = new ConcurrentHashMap<>();
|
||||
|
||||
public ObjectMapper() {
|
||||
ServiceLoader.load(TypeAdapterFactory.class).forEach(this::registerTypeAdapterFactory);
|
||||
ServiceLoader.load(TypeAdapter.class).forEach(this::registerTypeAdapter);
|
||||
}
|
||||
|
||||
public ObjectMapper registerTypeAdapter(Type type, TypeAdapter<?> adapter) {
|
||||
explicitAdapters.put(TypeToken.get(type), Objects.requireNonNull(adapter));
|
||||
public ObjectMapper registerTypeAdapter(Type type, TypeAdapter<?> adapter, boolean hierarchical) {
|
||||
(hierarchical ? hierarchyAdapters : explicitAdapters).put(TypeToken.get(type), Objects.requireNonNull(adapter));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMapper registerTypeAdapter(TypeAdapter<?> adapter) {
|
||||
SerializerFor annotation = adapter.getClass().getAnnotation(SerializerFor.class);
|
||||
if (annotation == null) {
|
||||
throw new IllegalArgumentException("TypeAdapter must be annotated with @SerializerFor to register it without specifying the target type");
|
||||
throw new IllegalArgumentException("TypeAdapter must be annotated with @SerializerFor to register it without specifying the target type: " + adapter.getClass().getName());
|
||||
}
|
||||
adapter = annotation.nullSafe() ? adapter.nullSafe() : adapter;
|
||||
for (Class<?> target : annotation.targets()) {
|
||||
registerTypeAdapter(target, adapter);
|
||||
registerTypeAdapter(target, adapter, annotation.hierarchical());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMapper registerTypeAdapterFactory(TypeAdapterFactory factory) {
|
||||
factories.add(Objects.requireNonNull(factory));
|
||||
factories.addFirst(Objects.requireNonNull(factory));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -60,6 +61,13 @@ public class ObjectMapper {
|
|||
if (explicitAdapters.containsKey(type)) {
|
||||
return (TypeAdapter<T>) explicitAdapters.get(type);
|
||||
}
|
||||
for (TypeToken<?> token : hierarchyAdapters.keySet()) {
|
||||
if (token.isAssignableFrom(type)) {
|
||||
TypeAdapter<T> adapter = (TypeAdapter<T>) hierarchyAdapters.get(token);
|
||||
explicitAdapters.put(type, adapter);
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
TypeAdapter<?> cached = typeTokenCache.get(type);
|
||||
if (cached != null) {
|
||||
return (TypeAdapter<T>) cached;
|
||||
|
|
|
@ -21,4 +21,9 @@ public @interface SerializerFor {
|
|||
* adapter. If {@code false}, the adapter will have to handle the {@code null} values.
|
||||
*/
|
||||
boolean nullSafe() default true;
|
||||
|
||||
/**
|
||||
* Whether this adapter should also be used for all subtypes of the target type.
|
||||
*/
|
||||
boolean hierarchical() default false;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public class DefaultDateTypeAdapter extends TypeAdapter<Date> {
|
|||
*/
|
||||
private final List<DateFormat> dateFormats = new ArrayList<>();
|
||||
|
||||
DefaultDateTypeAdapter() {
|
||||
public DefaultDateTypeAdapter() {
|
||||
dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US));
|
||||
if (!Locale.getDefault().equals(Locale.US)) {
|
||||
dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
|
||||
|
|
|
@ -438,7 +438,7 @@ public class TypeAdapters {
|
|||
}
|
||||
}
|
||||
|
||||
@SerializerFor(targets = InetAddress.class)
|
||||
@SerializerFor(targets = InetAddress.class, hierarchical = true)
|
||||
public static class InetAddressTypeAdapter extends TypeAdapter<InetAddress> {
|
||||
@Override
|
||||
public <TEx extends Throwable, Writer extends SerializeWriter<TEx, Writer>> void serialize(InetAddress value, Writer writer) throws TEx, MalformedDataException {
|
||||
|
@ -589,7 +589,7 @@ public class TypeAdapters {
|
|||
}
|
||||
}
|
||||
|
||||
@SerializerFor(targets = DataElement.class)
|
||||
@SerializerFor(targets = DataElement.class, hierarchical = true)
|
||||
public static class DataElementTypeAdapter extends TypeAdapter<DataElement> {
|
||||
@Override
|
||||
public <TEx extends Throwable, Writer extends SerializeWriter<TEx, Writer>> void serialize(DataElement value, Writer writer) throws TEx, MalformedDataException {
|
||||
|
|
Loading…
Reference in New Issue