fix(serialize-databind): support custom map subtypes
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
d29f8876ef
commit
3cd8aba2d1
|
@ -32,23 +32,25 @@ public class MapTypeAdapterFactory implements TypeAdapterFactory {
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
// we don't define a type parameter for the key or value types
|
// we don't define a type parameter for the key or value types
|
||||||
TypeAdapter<T> result = new MapTypeAdapter(mapper, keyAndValueTypes[0], keyAdapter, keyAndValueTypes[1], valueAdapter);
|
TypeAdapter<T> result = new MapTypeAdapter(mapper, keyAndValueTypes[0], keyAdapter, keyAndValueTypes[1], valueAdapter, rawType);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
|
private static class MapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
|
||||||
private final TypeAdapter<K> keyTypeAdapter;
|
private final TypeAdapter<K> keyTypeAdapter;
|
||||||
private final TypeAdapter<V> valueTypeAdapter;
|
private final TypeAdapter<V> valueTypeAdapter;
|
||||||
|
private final Class<?> implClass;
|
||||||
|
|
||||||
public MapTypeAdapter(
|
public MapTypeAdapter(
|
||||||
ObjectMapper context,
|
ObjectMapper context,
|
||||||
Type keyType,
|
Type keyType,
|
||||||
TypeAdapter<K> keyTypeAdapter,
|
TypeAdapter<K> keyTypeAdapter,
|
||||||
Type valueType,
|
Type valueType,
|
||||||
TypeAdapter<V> valueTypeAdapter) {
|
TypeAdapter<V> valueTypeAdapter,
|
||||||
|
Class<?> implClass) {
|
||||||
this.keyTypeAdapter = new TypeAdapterRuntimeTypeWrapper<>(context, keyTypeAdapter, keyType);
|
this.keyTypeAdapter = new TypeAdapterRuntimeTypeWrapper<>(context, keyTypeAdapter, keyType);
|
||||||
this.valueTypeAdapter =
|
this.valueTypeAdapter = new TypeAdapterRuntimeTypeWrapper<>(context, valueTypeAdapter, valueType);
|
||||||
new TypeAdapterRuntimeTypeWrapper<>(context, valueTypeAdapter, valueType);
|
this.implClass = implClass.equals(Map.class) ? LinkedHashMap.class : implClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -102,7 +104,7 @@ public class MapTypeAdapterFactory implements TypeAdapterFactory {
|
||||||
@Override
|
@Override
|
||||||
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> Map<K, V> deserialize(Reader reader) throws TEx, MalformedDataException {
|
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> Map<K, V> deserialize(Reader reader) throws TEx, MalformedDataException {
|
||||||
Token peek = reader.peek();
|
Token peek = reader.peek();
|
||||||
Map<K, V> map = new HashMap<>();
|
Map<K, V> map = (Map<K, V>) TypeUtils.instantiate(implClass).orElseThrow(() -> new MalformedDataException("Could not instantiate map"));
|
||||||
if (peek == Token.BEGIN_ARRAY) {
|
if (peek == Token.BEGIN_ARRAY) {
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.gitlab.jfronny.commons.serialize.databind.test;
|
package io.gitlab.jfronny.commons.serialize.databind.test;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.commons.data.String2ObjectMap;
|
||||||
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
|
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
|
||||||
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
|
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
|
||||||
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
|
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
|
||||||
|
@ -35,4 +36,26 @@ public class MapAdapterTest {
|
||||||
assertEquals(de, ew.get());
|
assertEquals(de, ew.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testS2OMap() throws MalformedDataException {
|
||||||
|
DataElement.Object de = new DataElement.Object();
|
||||||
|
de.members().put("key", new DataElement.Primitive.String("value"));
|
||||||
|
de.members().put("key2", new DataElement.Primitive.String("value2"));
|
||||||
|
de.members().put("key3", new DataElement.Primitive.String("value3"));
|
||||||
|
ObjectMapper om = new ObjectMapper();
|
||||||
|
TypeAdapter<String2ObjectMap<String>> adapter = om.getAdapter(new TypeToken<>() {});
|
||||||
|
String2ObjectMap<String> map;
|
||||||
|
try (EmulatedReader er = new EmulatedReader(de)) {
|
||||||
|
map = adapter.deserialize(er);
|
||||||
|
}
|
||||||
|
assertEquals(3, map.size());
|
||||||
|
assertEquals("value", map.get("key"));
|
||||||
|
assertEquals("value2", map.get("key2"));
|
||||||
|
assertEquals("value3", map.get("key3"));
|
||||||
|
try (EmulatedWriter ew = new EmulatedWriter()) {
|
||||||
|
adapter.serialize(map, ew);
|
||||||
|
assertEquals(de, ew.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue