94 lines
3.9 KiB
Java
94 lines
3.9 KiB
Java
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
|
|
|
|
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
|
|
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
|
|
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
|
|
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
|
|
import io.gitlab.jfronny.commons.serialize.databind.api.TypeUtils;
|
|
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
|
|
import io.gitlab.jfronny.commons.serialize.SerializeReader;
|
|
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
|
|
import io.gitlab.jfronny.commons.serialize.Token;
|
|
|
|
import java.lang.reflect.Array;
|
|
import java.lang.reflect.GenericArrayType;
|
|
import java.lang.reflect.Type;
|
|
import java.util.ArrayList;
|
|
|
|
public class ArrayTypeAdapterFactory implements TypeAdapterFactory {
|
|
@Override
|
|
public <T> TypeAdapter<T> create(ObjectMapper mapper, TypeToken<T> typeToken) {
|
|
Type type = typeToken.getType();
|
|
if (!(type instanceof GenericArrayType || (type instanceof Class<?> cl && cl.isArray()))) {
|
|
return null;
|
|
}
|
|
Type componentType = TypeUtils.getArrayComponentType(type);
|
|
TypeAdapter<?> componentTypeAdapter = mapper.getAdapter(TypeToken.get(componentType));
|
|
//noinspection rawtypes,unchecked
|
|
return new ArrayTypeAdapter(mapper, componentTypeAdapter, TypeUtils.getRawType(componentType));
|
|
}
|
|
|
|
private static class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
|
|
private final Class<E> componentType;
|
|
private final TypeAdapter<E> componentTypeAdapter;
|
|
|
|
public ArrayTypeAdapter(ObjectMapper context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) {
|
|
this.componentTypeAdapter = new TypeAdapterRuntimeTypeWrapper<>(context, componentTypeAdapter, componentType);
|
|
this.componentType = componentType;
|
|
}
|
|
|
|
@Override
|
|
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(Object value, Writer writer) throws TEx, MalformedDataException {
|
|
if (value == null) {
|
|
writer.nullValue();
|
|
return;
|
|
}
|
|
writer.beginArray();
|
|
int length = Array.getLength(value);
|
|
for (int i = 0; i < length; i++) {
|
|
E element = (E) Array.get(value, i);
|
|
componentTypeAdapter.serialize(element, writer);
|
|
}
|
|
writer.endArray();
|
|
}
|
|
|
|
@Override
|
|
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> Object deserialize(Reader reader) throws TEx, MalformedDataException {
|
|
if (reader.peek() == Token.NULL) {
|
|
reader.nextNull();
|
|
return null;
|
|
}
|
|
if (reader.isLenient() && reader.peek() != Token.BEGIN_ARRAY) {
|
|
// Coerce
|
|
Object array = Array.newInstance(componentType, 1);
|
|
Array.set(array, 0, componentTypeAdapter.deserialize(reader));
|
|
return array;
|
|
}
|
|
|
|
ArrayList<E> list = new ArrayList<>();
|
|
reader.beginArray();
|
|
while (reader.hasNext()) {
|
|
E instance = componentTypeAdapter.deserialize(reader);
|
|
list.add(instance);
|
|
}
|
|
reader.endArray();
|
|
|
|
int size = list.size();
|
|
// Have to copy primitives one by one to primitive array
|
|
if (componentType.isPrimitive()) {
|
|
Object array = Array.newInstance(componentType, size);
|
|
for (int i = 0; i < size; i++) {
|
|
Array.set(array, i, list.get(i));
|
|
}
|
|
return array;
|
|
}
|
|
// But for Object[] can use ArrayList.toArray
|
|
else {
|
|
@SuppressWarnings("unchecked")
|
|
E[] array = (E[]) Array.newInstance(componentType, size);
|
|
return list.toArray(array);
|
|
}
|
|
}
|
|
}
|
|
}
|