in johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java [558:712]
public Map<String, Reader> findReaders(final Class<?> clazz) {
final Map<String, Reader> readers = delegate.findReaders(clazz);
final boolean record = isRecord(clazz) || Meta.getAnnotation(clazz, JohnzonRecord.class) != null;
final Map<String, Parameter> recordParams = record ?
findRecordConstructor(clazz)
.map(c -> Stream.of(c.getParameters())
.collect(toMap(p -> ofNullable(p.getAnnotation(JohnzonRecord.Name.class))
.map(JohnzonRecord.Name::value)
.orElseGet(p::getName), identity())))
.orElseGet(Collections::emptyMap) :
null;
final Comparator<String> keyComparator = fieldComparator(clazz);
final Map<String, Reader> result = keyComparator == null ? new HashMap<>() : new TreeMap<>(keyComparator);
for (final Map.Entry<String, Reader> entry : readers.entrySet()) {
final Reader initialReader = entry.getValue();
final DecoratedType annotations = record ? new DecoratedType() {
private final Parameter parameter = recordParams.get(entry.getKey());
@Override
public Type getType() {
return initialReader.getType();
}
@Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
final T annotation = initialReader.getAnnotation(clazz);
return annotation == null && parameter != null ? parameter.getAnnotation(clazz) : annotation;
}
@Override
public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
final T annotation = parameter == null ? null : parameter.getAnnotation(clazz);
return annotation == null ? initialReader.getClassOrPackageAnnotation(clazz) : annotation;
}
@Override
public Adapter<?, ?> findConverter() {
return initialReader.findConverter();
}
@Override
public boolean isNillable(final boolean globalConfig) {
return initialReader.isNillable(globalConfig);
}
} : initialReader;
if (isTransient(initialReader, visibility, clazz, true)) {
validateAnnotationsOnTransientField(initialReader);
continue;
}
if (annotations.getAnnotation(JohnzonAny.class) != null) {
continue;
}
final Reader finalReader;
if (FieldAndMethodAccessMode.CompositeDecoratedType.class.isInstance(initialReader)) { // unwrap to use the right reader
final FieldAndMethodAccessMode.CompositeDecoratedType decoratedType = FieldAndMethodAccessMode.CompositeDecoratedType.class.cast(initialReader);
final DecoratedType type2 = decoratedType.getType2();
if (MethodAccessMode.MethodReader.class.isInstance(type2)) {
finalReader = Reader.class.cast(type2);
} else {
finalReader = initialReader;
}
} else {
finalReader = initialReader;
}
// handle optionals since mapper is still only java 7
final Type type;
final Function<Object, Object> reader;
final Type readerType = finalReader.getType();
if (isOptional(readerType)) {
type = ParameterizedType.class.cast(readerType).getActualTypeArguments()[0];
reader = i -> ofNullable(finalReader.read(i)).map(o -> Optional.class.cast(o).orElse(null)).orElse(null);
} else if (OptionalInt.class == readerType) {
type = Integer.class;
reader = i -> {
final OptionalInt optionalInt = OptionalInt.class.cast(finalReader.read(i));
return optionalInt == null || !optionalInt.isPresent() ? null : optionalInt.getAsInt();
};
} else if (OptionalLong.class == readerType) {
type = Long.class;
reader = i -> {
final OptionalLong optionalLong = OptionalLong.class.cast(finalReader.read(i));
return optionalLong == null || !optionalLong.isPresent() ? null : optionalLong.getAsLong();
};
} else if (OptionalDouble.class == readerType) {
type = Double.class;
reader = i -> {
final OptionalDouble optionalDouble = OptionalDouble.class.cast(finalReader.read(i));
return optionalDouble == null || !optionalDouble.isPresent() ? null : optionalDouble.getAsDouble();
};
} else if (isOptionalArray(finalReader)) {
final Type optionalUnwrappedType = findOptionalType(GenericArrayType.class.cast(readerType).getGenericComponentType());
type = new GenericArrayTypeImpl(optionalUnwrappedType);
reader = i -> {
final Object[] optionals = Object[].class.cast(finalReader.read(i));
return optionals == null ?
null : Stream.of(optionals)
.map(Optional.class::cast)
.map(o -> o.orElse(null))
.toArray();
};
} else {
type = readerType;
reader = finalReader::read;
}
final WriterConverters writerConverters = new WriterConverters(annotations, types);
final JsonbProperty property = annotations.getAnnotation(JsonbProperty.class);
final JsonbNillable propertyNillable = annotations.getAnnotation(JsonbNillable.class);
final JsonbNillable classOrPackageNillable = annotations.getClassOrPackageAnnotation(JsonbNillable.class);
final boolean isNillable = isNillable(property, propertyNillable, classOrPackageNillable);
final String key = property == null || property.value().isEmpty() ? naming.translateName(entry.getKey()) : property.value();
if (result.put(key, new Reader() {
@Override
public Object read(final Object instance) {
return reader.apply(instance);
}
@Override
public ObjectConverter.Writer<?> findObjectConverterWriter() {
return writerConverters.writer;
}
@Override
public Type getType() {
return type;
}
@Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
return finalReader.getAnnotation(clazz);
}
@Override
public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
return finalReader.getClassOrPackageAnnotation(clazz);
}
@Override
public Adapter<?, ?> findConverter() {
return writerConverters.converter;
}
@Override
public boolean isNillable(final boolean global) {
return isNillable;
}
}) != null) {
throw new JsonbException("Ambiguous field " + key);
}
}
return result;
}