From 409bf29cd459937e9103de0664f428bd7c296058 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 28 Apr 2023 17:49:43 +0200 Subject: [PATCH] Unknown subtypes deserializiation decoupled from jackson version --- .../serialization/ElementDeserializer.java | 3 + .../serialization/ElementMapper.java | 101 ++++++++++++------ 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/gcube/informationsystem/serialization/ElementDeserializer.java b/src/main/java/org/gcube/informationsystem/serialization/ElementDeserializer.java index 2ff0edb..56ab767 100644 --- a/src/main/java/org/gcube/informationsystem/serialization/ElementDeserializer.java +++ b/src/main/java/org/gcube/informationsystem/serialization/ElementDeserializer.java @@ -27,8 +27,11 @@ import org.gcube.informationsystem.base.reference.Element; import org.gcube.informationsystem.types.TypeMapper; /** + * This is not used anymore. + * Keeping the class in case something is not solved * @author Luca Frosini (ISTI - CNR) */ +@Deprecated public class ElementDeserializer extends StdDeserializer { private static final long serialVersionUID = -2551569658316955137L; diff --git a/src/main/java/org/gcube/informationsystem/serialization/ElementMapper.java b/src/main/java/org/gcube/informationsystem/serialization/ElementMapper.java index c5bf200..674eb23 100644 --- a/src/main/java/org/gcube/informationsystem/serialization/ElementMapper.java +++ b/src/main/java/org/gcube/informationsystem/serialization/ElementMapper.java @@ -23,9 +23,7 @@ import org.gcube.com.fasterxml.jackson.databind.JsonMappingException; import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.SerializationFeature; -import org.gcube.com.fasterxml.jackson.databind.module.SimpleModule; import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; -import org.gcube.com.fasterxml.jackson.databind.node.JsonNodeType; import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.gcube.com.fasterxml.jackson.databind.node.TextNode; import org.gcube.informationsystem.base.reference.AccessType; @@ -82,7 +80,8 @@ public abstract class ElementMapper { if(!Type.class.isAssignableFrom(clz)) { Class dummyClz = accessType.getDummyImplementationClass(); if(dummyClz != null) { - ElementMapper.registerSubtypes(clz, dummyClz); + // ElementMapper.registerSubtypes(clz, dummyClz); + ElementMapper.registerSubtype(dummyClz); }else { ElementMapper.registerSubtype(clz); } @@ -115,14 +114,15 @@ public abstract class ElementMapper { } } - - public static void registerSubtypes(Class clz, Class implementationClass) { - String typeName = TypeMapper.getType(clz); - SimpleModule isModule = new SimpleModule(typeName); - isModule.addDeserializer(clz, new ElementDeserializer<>(clz, mapper)); - mapper.registerModule(isModule); - registerSubtype(implementationClass); - } + +// This add the ElementDeserializer which has been deprecated thank to the fix in +// public static void registerSubtypes(Class clz, Class implementationClass) { +// String typeName = TypeMapper.getType(clz); +// SimpleModule isModule = new SimpleModule(typeName); +// isModule.addDeserializer(clz, new ElementDeserializer<>(clz, mapper)); +// mapper.registerModule(isModule); +// registerSubtype(implementationClass); +// } public static void registerSubtype(Class clz) { String typeName = TypeMapper.getType(clz); @@ -200,9 +200,9 @@ public abstract class ElementMapper { return stringBuffer; } - protected static JsonNode setAvailableSuperclass(JsonNode jsonNode) { - String unknownType = jsonNode.get(Element.TYPE_PROPERTY).asText(); - ArrayNode arrayNode = (ArrayNode) jsonNode.get(Element.SUPERTYPES_PROPERTY); + protected static ObjectNode setTypeToBestAvailable(ObjectNode objectNode) { + String unknownType = objectNode.get(Element.TYPE_PROPERTY).asText(); + ArrayNode arrayNode = (ArrayNode) objectNode.get(Element.SUPERTYPES_PROPERTY); String candidatedSupertype = null; for(int i = 0; i < arrayNode.size(); i++) { @@ -227,34 +227,67 @@ public abstract class ElementMapper { } if(candidatedSupertype!=null) { - if(!jsonNode.has(Element.EXPECTED_TYPE_PROPERTY)) { - ((ObjectNode) jsonNode).set(Element.EXPECTED_TYPE_PROPERTY, jsonNode.get(Element.TYPE_PROPERTY)); + if(!objectNode.has(Element.EXPECTED_TYPE_PROPERTY)) { + objectNode.set(Element.EXPECTED_TYPE_PROPERTY, objectNode.get(Element.TYPE_PROPERTY)); } - ((ObjectNode) jsonNode).set(Element.TYPE_PROPERTY, new TextNode(candidatedSupertype)); - ((ObjectNode) jsonNode).remove(Element.SUPERTYPES_PROPERTY); - return jsonNode; + objectNode.set(Element.TYPE_PROPERTY, new TextNode(candidatedSupertype)); + objectNode.remove(Element.SUPERTYPES_PROPERTY); + return objectNode; } StringBuffer stringBuffer = getError(unknownType); - logger.trace("Unable to unmarshall {}. {}", jsonNode.toString(), stringBuffer.toString()); + logger.trace("Unable to unmarshall {}. {}", objectNode.toString(), stringBuffer.toString()); throw new RuntimeException(stringBuffer.toString()); } - protected static JsonNode analizeFullJson(JsonNode jsonNode) { - String cls = jsonNode.get(Element.TYPE_PROPERTY).asText(); + protected static JsonNode analizeTypes(ObjectNode objectNode) { + String cls = objectNode.get(Element.TYPE_PROPERTY).asText(); if(!knownTypes.containsKey(cls)) { - jsonNode = setAvailableSuperclass(jsonNode); + objectNode = setTypeToBestAvailable(objectNode); } - Iterator iterator = jsonNode.fieldNames(); + Iterator iterator = objectNode.fieldNames(); while(iterator.hasNext()) { String fieldName = iterator.next(); - JsonNode jn = jsonNode.get(fieldName); - if(jn.getNodeType() == JsonNodeType.OBJECT) { - jn = analizeFullJson(jn); - ((ObjectNode) jsonNode).set(fieldName, jn); + JsonNode jn = objectNode.get(fieldName); + switch (jn.getNodeType()) { + case OBJECT: + jn = analizeTypes((ObjectNode)jn); + break; + + case ARRAY: + jn = analizeTypes((ArrayNode) jn); + break; + + default: + break; } + objectNode.replace(fieldName, jn); } - return jsonNode; + return objectNode; + } + + protected static ArrayNode analizeTypes(ArrayNode arrayNode) { + ArrayNode ret = mapper.createArrayNode(); + + for(JsonNode jsonNode : arrayNode) { + + switch (jsonNode.getNodeType()) { + case OBJECT: + jsonNode = analizeTypes((ObjectNode) jsonNode); + break; + + case ARRAY: + jsonNode = analizeTypes((ArrayNode) jsonNode); + break; + + default: + break; + } + + ret.add(jsonNode); + } + + return ret; } /** @@ -273,7 +306,7 @@ public abstract class ElementMapper { return mapper.readValue(reader, clz); } catch (JsonMappingException e) { JsonNode jsonNode = mapper.readTree(reader); - jsonNode = analizeFullJson(jsonNode); + jsonNode = analizeTypes((ObjectNode) jsonNode); return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)); } } @@ -294,7 +327,7 @@ public abstract class ElementMapper { return mapper.readValue(stream, clz); } catch (JsonMappingException e) { JsonNode jsonNode = mapper.readTree(stream); - jsonNode = analizeFullJson(jsonNode); + jsonNode = analizeTypes((ObjectNode) jsonNode); return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)); } } @@ -314,7 +347,7 @@ public abstract class ElementMapper { return mapper.readValue(string, clz); } catch (JsonMappingException e) { JsonNode jsonNode = mapper.readTree(string); - jsonNode = analizeFullJson(jsonNode); + jsonNode = analizeTypes((ObjectNode) jsonNode); return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)); } } @@ -328,7 +361,7 @@ public abstract class ElementMapper { List ret = new ArrayList<>(); ArrayNode arrayNode = (ArrayNode) mapper.readTree(string); for(JsonNode jsonNode : arrayNode) { - jsonNode = analizeFullJson(jsonNode); + jsonNode = analizeTypes((ObjectNode) jsonNode); ret.add(ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode))); } return ret; @@ -344,7 +377,7 @@ public abstract class ElementMapper { List ret = new ArrayList<>(); ArrayNode arrayNode = (ArrayNode) mapper.readTree(string); for(JsonNode jsonNode : arrayNode) { - jsonNode = analizeFullJson(jsonNode); + jsonNode = analizeTypes((ObjectNode) jsonNode); ret.add((El) ElementMapper.unmarshal(Element.class, mapper.writeValueAsString(jsonNode))); } return ret;