net.hamnaberg.json.codec.reflection.ReflectionCodec Maven / Gradle / Ivy
package net.hamnaberg.json.codec.reflection;
import io.vavr.collection.List;
import io.vavr.control.Option;
import net.hamnaberg.json.codec.Codecs;
import net.hamnaberg.json.codec.DecodeResult;
import net.hamnaberg.json.Json;
import net.hamnaberg.json.codec.JsonCodec;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Predicate;
public final class ReflectionCodec implements JsonCodec {
private final Class type;
private final Map> codecs;
private final List fields;
private final Factory factory;
private static Map, JsonCodec>> defaultCodecs;
static {
Map, JsonCodec>> codecs = new HashMap<>();
codecs.put(String.class, Codecs.CString);
codecs.put(Integer.class, Codecs.CInt);
codecs.put(int.class, Codecs.CInt);
codecs.put(double.class, Codecs.CDouble);
codecs.put(long.class, Codecs.CLong);
codecs.put(Long.class, Codecs.CLong);
codecs.put(Double.class, Codecs.CDouble);
codecs.put(BigInteger.class, Codecs.CNumber);
codecs.put(Number.class, Codecs.CNumber);
codecs.put(Boolean.class, Codecs.CBoolean);
defaultCodecs = Collections.unmodifiableMap(codecs);
}
public ReflectionCodec(Class type) {
this(type, Collections.emptyMap());
}
public ReflectionCodec(Class type, Map> codecs) {
this(type, codecs, (p) -> true, Option.none());
}
public ReflectionCodec(Class type, Map> codecs, Predicate predicate) {
this(type, codecs, predicate, Option.none());
}
public ReflectionCodec(Class type, Map> codecs, Predicate predicate, Option factoryMethod) {
this.type = type;
this.codecs = codecs;
this.fields = getFields(type).filter(predicate);
this.factory = factoryMethod.map(n -> Factory.factory(type, n, fields)).getOrElse(Factory.constructor(type, fields));
}
@Override
public Json.JValue toJson(A value) {
Map map = new LinkedHashMap<>();
for (Param field : fields) {
Option> codec = getCodec(field);
Option