io.airlift.json.RecordAutoDetectModule Maven / Gradle / Ivy
package io.airlift.json;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.RecordComponent;
import java.util.Set;
import java.util.stream.Stream;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
public class RecordAutoDetectModule
extends SimpleModule
{
@Deprecated(forRemoval = true)
@Retention(RUNTIME)
@Target(TYPE)
public @interface LegacyRecordIntrospection {}
@Override
public void setupModule(SetupContext context)
{
super.setupModule(context);
context.insertAnnotationIntrospector(new Introspector());
}
private static class Introspector
extends AnnotationIntrospector
{
private static final VisibilityChecker.Std RECORD_VISIBILITY_CHECKER = VisibilityChecker.Std.defaultInstance()
.withGetterVisibility(JsonAutoDetect.Visibility.PUBLIC_ONLY)
.withCreatorVisibility(JsonAutoDetect.Visibility.DEFAULT)
.withFieldVisibility(JsonAutoDetect.Visibility.DEFAULT)
.withIsGetterVisibility(JsonAutoDetect.Visibility.DEFAULT);
@Override
public VisibilityChecker> findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker> checker)
{
if (ac.getRawType().isRecord()) {
JsonAutoDetect overrideAnnotation = ac.getRawType().getAnnotation(JsonAutoDetect.class);
if (overrideAnnotation != null) {
return VisibilityChecker.Std.construct(JsonAutoDetect.Value.from(overrideAnnotation));
}
if (ac.getRawType().isAnnotationPresent(LegacyRecordIntrospection.class)) {
return RECORD_VISIBILITY_CHECKER;
}
return new RecordVisibilityChecker(ac.getRawType().asSubclass(Record.class));
}
return checker;
}
@Override
public Version version()
{
return Version.unknownVersion();
}
}
private static class RecordVisibilityChecker
implements VisibilityChecker
{
private final Set componentNames;
public RecordVisibilityChecker(Class extends Record> recordClass)
{
componentNames = Stream.of(recordClass.getRecordComponents())
.map(RecordComponent::getName)
.collect(toImmutableSet());
}
@Override
public RecordVisibilityChecker with(JsonAutoDetect annotation)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withOverrides(JsonAutoDetect.Value value)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker with(JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withVisibility(PropertyAccessor propertyAccessor, JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withGetterVisibility(JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withIsGetterVisibility(JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withSetterVisibility(JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withCreatorVisibility(JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public RecordVisibilityChecker withFieldVisibility(JsonAutoDetect.Visibility visibility)
{
throw new UnsupportedOperationException();
}
@Override
public boolean isGetterVisible(Method method)
{
if (!Modifier.isPublic(method.getModifiers())) {
return false;
}
return componentNames.contains(method.getName());
}
@Override
public boolean isGetterVisible(AnnotatedMethod annotatedMethod)
{
return isGetterVisible(annotatedMethod.getAnnotated());
}
@Override
public boolean isIsGetterVisible(Method method)
{
return false;
}
@Override
public boolean isIsGetterVisible(AnnotatedMethod annotatedMethod)
{
return false;
}
@Override
public boolean isSetterVisible(Method method)
{
return false;
}
@Override
public boolean isSetterVisible(AnnotatedMethod annotatedMethod)
{
return false;
}
@Override
public boolean isCreatorVisible(Member member)
{
return true;
}
@Override
public boolean isCreatorVisible(AnnotatedMember annotatedMember)
{
return true;
}
@Override
public boolean isFieldVisible(Field field)
{
return false;
}
@Override
public boolean isFieldVisible(AnnotatedField field)
{
return false;
}
}
}