|
21 | 21 | import com.fasterxml.jackson.databind.JsonMappingException;
|
22 | 22 | import jakarta.validation.ConstraintViolationException;
|
23 | 23 | import java.io.IOException;
|
| 24 | +import java.lang.reflect.InvocationTargetException; |
| 25 | +import java.lang.reflect.Method; |
| 26 | +import java.util.ArrayList; |
24 | 27 | import java.util.Collection;
|
25 | 28 |
|
26 | 29 | public class DeserializeHelper {
|
27 | 30 |
|
28 | 31 | public static <T> T deserializeOneOf(
|
29 |
| - JsonParser p, Class<T> targetClass, Collection<Class<?>> unionTypes) throws IOException { |
| 32 | + JsonParser p, Class<T> targetClass, Collection<Class<?>> oneOfTypes) throws IOException { |
30 | 33 | TreeNode node = p.readValueAsTree();
|
31 |
| - JsonProcessingException ex = |
32 |
| - new JsonMappingException(p, "Problem deserializing " + targetClass); |
33 |
| - for (Class<?> unionType : unionTypes) { |
34 |
| - try { |
35 |
| - Object object = p.getCodec().treeToValue(node, unionType); |
36 |
| - return targetClass.getConstructor(unionType).newInstance(object); |
37 |
| - } catch (IOException | ReflectiveOperationException | ConstraintViolationException io) { |
38 |
| - ex.addSuppressed(io); |
| 34 | + try { |
| 35 | + T result = targetClass.getDeclaredConstructor().newInstance(); |
| 36 | + Collection<Exception> exceptions = new ArrayList<>(); |
| 37 | + for (Class<?> oneOfType : oneOfTypes) { |
| 38 | + try { |
| 39 | + assingIt(p, result, node, targetClass, oneOfType); |
| 40 | + break; |
| 41 | + } catch (IOException | ConstraintViolationException | InvocationTargetException ex) { |
| 42 | + exceptions.add(ex); |
| 43 | + } |
| 44 | + } |
| 45 | + if (exceptions.size() == oneOfTypes.size()) { |
| 46 | + JsonMappingException ex = |
| 47 | + new JsonMappingException( |
| 48 | + p, |
| 49 | + String.format( |
| 50 | + "Error deserializing class %s, all oneOf alternatives %s has failed ", |
| 51 | + targetClass, oneOfTypes)); |
| 52 | + exceptions.forEach(ex::addSuppressed); |
| 53 | + throw ex; |
| 54 | + } |
| 55 | + return result; |
| 56 | + } catch (ReflectiveOperationException ex) { |
| 57 | + throw new IllegalStateException(ex); |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + private static <T> void assingIt( |
| 62 | + JsonParser p, T result, TreeNode node, Class<T> targetClass, Class<?> type) |
| 63 | + throws JsonProcessingException, ReflectiveOperationException { |
| 64 | + findSetMethod(targetClass, type).invoke(result, p.getCodec().treeToValue(node, type)); |
| 65 | + } |
| 66 | + |
| 67 | + private static Method findSetMethod(Class<?> targetClass, Class<?> type) { |
| 68 | + for (Method method : targetClass.getMethods()) { |
| 69 | + OneOfSetter oneOfSetter = method.getAnnotation(OneOfSetter.class); |
| 70 | + if (oneOfSetter != null && type.equals(oneOfSetter.value())) { |
| 71 | + return method; |
39 | 72 | }
|
40 | 73 | }
|
41 |
| - throw ex; |
| 74 | + throw new IllegalStateException("Cannot find a setter for type " + type); |
42 | 75 | }
|
43 | 76 |
|
44 | 77 | public static <T> T deserializeItem(JsonParser p, Class<T> targetClass, Class<?> valueClass)
|
|
0 commit comments