Unknown subtypes deserializiation decoupled from jackson version

This commit is contained in:
Luca Frosini 2023-04-28 17:49:43 +02:00
parent 4b06b1b6bc
commit 409bf29cd4
2 changed files with 70 additions and 34 deletions

View File

@ -27,8 +27,11 @@ import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.types.TypeMapper; 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) * @author Luca Frosini (ISTI - CNR)
*/ */
@Deprecated
public class ElementDeserializer<ISM extends Element> extends StdDeserializer<ISM> { public class ElementDeserializer<ISM extends Element> extends StdDeserializer<ISM> {
private static final long serialVersionUID = -2551569658316955137L; private static final long serialVersionUID = -2551569658316955137L;

View File

@ -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.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.SerializationFeature; 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.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.ObjectNode;
import org.gcube.com.fasterxml.jackson.databind.node.TextNode; import org.gcube.com.fasterxml.jackson.databind.node.TextNode;
import org.gcube.informationsystem.base.reference.AccessType; import org.gcube.informationsystem.base.reference.AccessType;
@ -82,7 +80,8 @@ public abstract class ElementMapper {
if(!Type.class.isAssignableFrom(clz)) { if(!Type.class.isAssignableFrom(clz)) {
Class<Element> dummyClz = accessType.getDummyImplementationClass(); Class<Element> dummyClz = accessType.getDummyImplementationClass();
if(dummyClz != null) { if(dummyClz != null) {
ElementMapper.registerSubtypes(clz, dummyClz); // ElementMapper.registerSubtypes(clz, dummyClz);
ElementMapper.registerSubtype(dummyClz);
}else { }else {
ElementMapper.registerSubtype(clz); ElementMapper.registerSubtype(clz);
} }
@ -115,14 +114,15 @@ public abstract class ElementMapper {
} }
} }
public static <El extends Element> void registerSubtypes(Class<El> clz, Class<El> implementationClass) { // This add the ElementDeserializer which has been deprecated thank to the fix in
String typeName = TypeMapper.getType(clz); // public static <El extends Element> void registerSubtypes(Class<El> clz, Class<El> implementationClass) {
SimpleModule isModule = new SimpleModule(typeName); // String typeName = TypeMapper.getType(clz);
isModule.addDeserializer(clz, new ElementDeserializer<>(clz, mapper)); // SimpleModule isModule = new SimpleModule(typeName);
mapper.registerModule(isModule); // isModule.addDeserializer(clz, new ElementDeserializer<>(clz, mapper));
registerSubtype(implementationClass); // mapper.registerModule(isModule);
} // registerSubtype(implementationClass);
// }
public static <El extends Element> void registerSubtype(Class<El> clz) { public static <El extends Element> void registerSubtype(Class<El> clz) {
String typeName = TypeMapper.getType(clz); String typeName = TypeMapper.getType(clz);
@ -200,9 +200,9 @@ public abstract class ElementMapper {
return stringBuffer; return stringBuffer;
} }
protected static JsonNode setAvailableSuperclass(JsonNode jsonNode) { protected static ObjectNode setTypeToBestAvailable(ObjectNode objectNode) {
String unknownType = jsonNode.get(Element.TYPE_PROPERTY).asText(); String unknownType = objectNode.get(Element.TYPE_PROPERTY).asText();
ArrayNode arrayNode = (ArrayNode) jsonNode.get(Element.SUPERTYPES_PROPERTY); ArrayNode arrayNode = (ArrayNode) objectNode.get(Element.SUPERTYPES_PROPERTY);
String candidatedSupertype = null; String candidatedSupertype = null;
for(int i = 0; i < arrayNode.size(); i++) { for(int i = 0; i < arrayNode.size(); i++) {
@ -227,34 +227,67 @@ public abstract class ElementMapper {
} }
if(candidatedSupertype!=null) { if(candidatedSupertype!=null) {
if(!jsonNode.has(Element.EXPECTED_TYPE_PROPERTY)) { if(!objectNode.has(Element.EXPECTED_TYPE_PROPERTY)) {
((ObjectNode) jsonNode).set(Element.EXPECTED_TYPE_PROPERTY, jsonNode.get(Element.TYPE_PROPERTY)); objectNode.set(Element.EXPECTED_TYPE_PROPERTY, objectNode.get(Element.TYPE_PROPERTY));
} }
((ObjectNode) jsonNode).set(Element.TYPE_PROPERTY, new TextNode(candidatedSupertype)); objectNode.set(Element.TYPE_PROPERTY, new TextNode(candidatedSupertype));
((ObjectNode) jsonNode).remove(Element.SUPERTYPES_PROPERTY); objectNode.remove(Element.SUPERTYPES_PROPERTY);
return jsonNode; return objectNode;
} }
StringBuffer stringBuffer = getError(unknownType); 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()); throw new RuntimeException(stringBuffer.toString());
} }
protected static JsonNode analizeFullJson(JsonNode jsonNode) { protected static JsonNode analizeTypes(ObjectNode objectNode) {
String cls = jsonNode.get(Element.TYPE_PROPERTY).asText(); String cls = objectNode.get(Element.TYPE_PROPERTY).asText();
if(!knownTypes.containsKey(cls)) { if(!knownTypes.containsKey(cls)) {
jsonNode = setAvailableSuperclass(jsonNode); objectNode = setTypeToBestAvailable(objectNode);
} }
Iterator<String> iterator = jsonNode.fieldNames(); Iterator<String> iterator = objectNode.fieldNames();
while(iterator.hasNext()) { while(iterator.hasNext()) {
String fieldName = iterator.next(); String fieldName = iterator.next();
JsonNode jn = jsonNode.get(fieldName); JsonNode jn = objectNode.get(fieldName);
if(jn.getNodeType() == JsonNodeType.OBJECT) { switch (jn.getNodeType()) {
jn = analizeFullJson(jn); case OBJECT:
((ObjectNode) jsonNode).set(fieldName, jn); 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); return mapper.readValue(reader, clz);
} catch (JsonMappingException e) { } catch (JsonMappingException e) {
JsonNode jsonNode = mapper.readTree(reader); JsonNode jsonNode = mapper.readTree(reader);
jsonNode = analizeFullJson(jsonNode); jsonNode = analizeTypes((ObjectNode) jsonNode);
return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)); return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode));
} }
} }
@ -294,7 +327,7 @@ public abstract class ElementMapper {
return mapper.readValue(stream, clz); return mapper.readValue(stream, clz);
} catch (JsonMappingException e) { } catch (JsonMappingException e) {
JsonNode jsonNode = mapper.readTree(stream); JsonNode jsonNode = mapper.readTree(stream);
jsonNode = analizeFullJson(jsonNode); jsonNode = analizeTypes((ObjectNode) jsonNode);
return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)); return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode));
} }
} }
@ -314,7 +347,7 @@ public abstract class ElementMapper {
return mapper.readValue(string, clz); return mapper.readValue(string, clz);
} catch (JsonMappingException e) { } catch (JsonMappingException e) {
JsonNode jsonNode = mapper.readTree(string); JsonNode jsonNode = mapper.readTree(string);
jsonNode = analizeFullJson(jsonNode); jsonNode = analizeTypes((ObjectNode) jsonNode);
return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)); return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode));
} }
} }
@ -328,7 +361,7 @@ public abstract class ElementMapper {
List<El> ret = new ArrayList<>(); List<El> ret = new ArrayList<>();
ArrayNode arrayNode = (ArrayNode) mapper.readTree(string); ArrayNode arrayNode = (ArrayNode) mapper.readTree(string);
for(JsonNode jsonNode : arrayNode) { for(JsonNode jsonNode : arrayNode) {
jsonNode = analizeFullJson(jsonNode); jsonNode = analizeTypes((ObjectNode) jsonNode);
ret.add(ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode))); ret.add(ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode)));
} }
return ret; return ret;
@ -344,7 +377,7 @@ public abstract class ElementMapper {
List<El> ret = new ArrayList<>(); List<El> ret = new ArrayList<>();
ArrayNode arrayNode = (ArrayNode) mapper.readTree(string); ArrayNode arrayNode = (ArrayNode) mapper.readTree(string);
for(JsonNode jsonNode : arrayNode) { for(JsonNode jsonNode : arrayNode) {
jsonNode = analizeFullJson(jsonNode); jsonNode = analizeTypes((ObjectNode) jsonNode);
ret.add((El) ElementMapper.unmarshal(Element.class, mapper.writeValueAsString(jsonNode))); ret.add((El) ElementMapper.unmarshal(Element.class, mapper.writeValueAsString(jsonNode)));
} }
return ret; return ret;