Skip to content

Instantly share code, notes, and snippets.

@MikeDombo
Created May 14, 2021 18:53
Show Gist options
  • Save MikeDombo/49b410f9561451a3a96f72322e4308f0 to your computer and use it in GitHub Desktop.
Save MikeDombo/49b410f9561451a3a96f72322e4308f0 to your computer and use it in GitHub Desktop.
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.fasterxml.jackson.jr.ob.impl;
import com.amazon.aws.iot.greengrass.JsonBuilder;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.jr.ob.JSONObjectException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Optional;
public class LombokBuilderBeanReader extends BeanReader {
private final Optional<Class<?>> builderClass;
private final Optional<Method> builderMethod;
private final Optional<Method> buildMethod;
public LombokBuilderBeanReader(Class<?> type, BeanReader defaultReader) {
super(type, defaultReader._propsByName, defaultReader._defaultCtor, defaultReader._stringCtor,
defaultReader._longCtor, defaultReader._ignorableNames, defaultReader._aliasMapping);
// To use Lombok builder for deserialization, the builder must be annotated with @JsonBuilder
builderClass =
Arrays.stream(_valueType.getDeclaredClasses())
.filter(a -> a.getAnnotation(JsonBuilder.class) != null)
.findFirst();
builderMethod = builderClass.flatMap(builderClass -> Arrays.stream(_valueType.getDeclaredMethods())
.filter(m -> m.getName().equals("builder") && m.getParameterCount() == 0)
.findFirst());
buildMethod = builderClass.flatMap(builderClass -> Arrays.stream(builderClass.getDeclaredMethods())
.filter(n -> n.getName().equals("build") && n.getParameterCount() == 0)
.findFirst());
}
@Override
public BeanPropertyReader findProperty(String name) {
return wrapReader(super.findProperty(name));
}
private BeanPropertyReader wrapReader(BeanPropertyReader beanPropertyReader) {
if (beanPropertyReader == null) {
return beanPropertyReader;
}
if (builderClass.isPresent()) {
Method setter;
try {
// Find builder setter for the type or any super type
setter = Arrays.stream(builderClass.get().getDeclaredMethods())
.filter(n -> n.getName().equals(beanPropertyReader.getName()) && n.getParameterCount() == 1 && n
.getParameterTypes()[0].isAssignableFrom(beanPropertyReader.rawSetterType()))
.findFirst().get();
} catch (NoSuchElementException e) {
try {
setter = builderClass.get().getDeclaredMethod(beanPropertyReader.getName(), String.class);
} catch (NoSuchMethodException ex) {
return beanPropertyReader;
}
}
return new BeanPropertyReader(beanPropertyReader.getName(), null, setter)
.withReader(beanPropertyReader.getReader());
}
return beanPropertyReader;
}
@Override
protected Object create() throws Exception {
if (builderClass.isPresent() && builderMethod.isPresent()) {
return builderMethod.get().invoke(null, (Object[]) null);
}
return super.create();
}
@Override
public Object readNext(JSONReader r, JsonParser p) throws IOException {
Object b = super.readNext(r, p);
return runBuildOnBuilder(p, b);
}
@Override
public Object read(JSONReader reader, JsonParser p) throws IOException {
Object b = super.read(reader, p);
return runBuildOnBuilder(p, b);
}
private Object runBuildOnBuilder(JsonParser p, Object b) throws IOException {
if (b == null) {
return b;
}
if (buildMethod.isPresent()) {
try {
return buildMethod.get().invoke(b, (Object[]) null);
} catch (InvocationTargetException | IllegalAccessException e) {
throw JSONObjectException.from(p, e.getCause() == null ? e : e.getCause(),
e.getCause() == null ? e.getMessage() : e.getCause().getMessage());
}
}
return b;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment