in johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java [726:831]
public Map<String, Writer> findWriters(final Class<?> clazz) {
final Map<String, Writer> writers = delegate.findWriters(clazz);
final Comparator<String> keyComparator = fieldComparator(clazz);
final Map<String, Writer> result = keyComparator == null ? new HashMap<>() : new TreeMap<>(keyComparator);
for (final Map.Entry<String, Writer> entry : writers.entrySet()) {
Writer initialWriter = entry.getValue();
if (isTransient(initialWriter, visibility, clazz, false)) {
validateAnnotationsOnTransientField(initialWriter);
continue;
}
final Writer finalWriter;
if (FieldAndMethodAccessMode.CompositeDecoratedType.class.isInstance(initialWriter)) { // unwrap to use the right reader
final FieldAndMethodAccessMode.CompositeDecoratedType decoratedType = FieldAndMethodAccessMode.CompositeDecoratedType.class.cast(initialWriter);
final DecoratedType type2 = decoratedType.getType2();
if (MethodAccessMode.MethodWriter.class.isInstance(type2)) {
finalWriter = Writer.class.cast(type2);
} else {
finalWriter = initialWriter;
}
} else {
finalWriter = initialWriter;
}
// handle optionals since mapper is still only java 7
final Type type;
final BiConsumer<Object, Object> writer;
final Type writerType = initialWriter.getType();
if (isOptional(writerType)) {
type = findOptionalType(writerType);
writer = (i, val) -> finalWriter.write(i, Optional.ofNullable(val));
} else if (OptionalInt.class == writerType) {
type = Integer.class;
writer = (i, value) -> finalWriter.write(i, value == null ?
OptionalInt.empty() : OptionalInt.of(Number.class.cast(value).intValue()));
} else if (OptionalLong.class == writerType) {
type = Long.class;
writer = (i, value) -> finalWriter.write(i, value == null ?
OptionalLong.empty() : OptionalLong.of(Number.class.cast(value).longValue()));
} else if (OptionalDouble.class == writerType) {
type = Double.class;
writer = (i, value) -> finalWriter.write(i, value == null ?
OptionalDouble.empty() : OptionalDouble.of(Number.class.cast(value).doubleValue()));
} else if (isOptionalArray(initialWriter)) {
final Type optionalUnwrappedType = findOptionalType(GenericArrayType.class.cast(writerType).getGenericComponentType());
type = new GenericArrayTypeImpl(optionalUnwrappedType);
writer = (i, value) -> {
if (value != null) {
finalWriter.write(i, Stream.of(Object[].class.cast(value))
.map(Optional::ofNullable)
.toArray(Optional[]::new));
}
};
} else {
type = writerType;
writer = finalWriter::write;
}
final ReaderConverters converters = new ReaderConverters(initialWriter);
final JsonbProperty property = initialWriter.getAnnotation(JsonbProperty.class);
final JsonbNillable propertyNillable = initialWriter.getAnnotation(JsonbNillable.class);
final JsonbNillable classOrPackageNillable = initialWriter.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 Writer() {
@Override
public void write(final Object instance, final Object val) {
writer.accept(instance, val);
}
@Override
public ObjectConverter.Reader<?> findObjectConverterReader() {
return converters.reader;
}
@Override
public Type getType() {
return type;
}
@Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
return initialWriter.getAnnotation(clazz);
}
@Override
public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
return initialWriter.getClassOrPackageAnnotation(clazz);
}
@Override
public Adapter<?, ?> findConverter() {
return converters.converter;
}
@Override
public boolean isNillable(final boolean global) {
return isNillable;
}
}) != null) {
throw new JsonbException("Ambiguous field " + key);
}
}
return result;
}