JType (String nodeName, JsonNode node, JsonNode parent, JPackage _package, Schema schema) { if (node.has("enum")) return null; JsonNode allOf = node.get("allOf"); JsonNode anyOf = node.get("anyOf"); JsonNode oneOf = node.get("oneOf"); Set<String> typeNames = null; ArrayNode arrayNode = null; String arrayNodeName = null; if (anyOf != null && anyOf.isArray() && anyOf.size() > 1 && oneOf == null && allOf == null) { arrayNodeName = "anyOf"; arrayNode = (ArrayNode)anyOf; } else if (oneOf != null && oneOf.isArray() && oneOf.size() > 1 && anyOf == null && allOf == null) { arrayNodeName = "oneOf"; arrayNode = (ArrayNode)oneOf; } else { typeNames = getTypeNames(node); typeNames.remove("array"); typeNames.remove("object"); } Map<String, List<ResolvedType>> resolved; if (arrayNode != null) { resolved = preprocess(arrayNode, arrayNodeName, schema); } else { if (typeNames.size() <= 1) { return null; } var fromCache = ruleFactory.getPrimitiveTypeFromCache(nodeName, typeNames); if (fromCache != null) { return fromCache; } resolved = new HashMap<>(); for (String type : typeNames) { resolved.computeIfAbsent(type, (k) -> new ArrayList<>()).add(new ResolvedPrimitiveType(type)); } } if (schema.getJavaType() != null) { return schema.getJavaType(); } JsonNode lenientDeserializerNode = node.get("javaLenientDeserialize"); boolean lenientDeserialize = lenientDeserializerNode != null && lenientDeserializerNode.asBoolean(false); if (resolved.entrySet().stream().anyMatch(entry -> !"object".equals(entry.getKey()) && entry.getValue().size() > 1)) { ruleFactory.getLogger() .error("Only one kind of non-object type can be specified within " + arrayNodeName + ". Error for : " + nodeName); return null; } if (resolved.containsKey(null)) { ruleFactory.getLogger().error("One of " + arrayNodeName + " branches has unspecified type. Error for : " + nodeName); return null; } JClass objectsSuperType = null; JDefinedClass wrapperClass = null; if (resolved.keySet().size() > 1) { wrapperClass = createClass(nodeName, node, _package, false); Map<String, Object> map = new HashMap<>(); map.put("tokens", new HashSet<>(resolved.keySet())); wrapperClass.metadata = map; schema.setJavaTypeIfEmpty(wrapperClass); if (typeNames != null) { ruleFactory.storePrimitiveTypeInCache(nodeName, typeNames, wrapperClass); } } @SuppressWarnings({"unchecked", "rawtypes"}) List<ResolvedClassType> objects = (List<ResolvedClassType>)(List)resolved.get("object"); if (objects != null) { if (objects.size() == 1) { ResolvedClassType obj = objects.get(0); objectsSuperType = (JClass)obj.generate(ruleFactory, nodeName + "-object", arrayNode, _package); schema.setJavaTypeIfEmpty(objectsSuperType); } else if (objects.size() > 1) { String determinantPropertyName = findDeterminantField(objects); final JDefinedClass superType; if (determinantPropertyName != null) { // Enum based deserialization superType = createClass(nodeName + "-base", node, _package, true); schema.setJavaTypeIfEmpty(superType); generateEnumClass(nodeName, schema, objects, determinantPropertyName, superType); Map<String, JType> subTypes = generateEnumBasedSubTypes(nodeName, arrayNode, objects, determinantPropertyName, superType, _package); annotateWithEnumBasedSubtypes(superType, subTypes, determinantPropertyName); } else if (suitableForDeductionBased(objects)) { // Deduction based deserialization superType = createClass(nodeName + "-base", node, _package, true); schema.setJavaTypeIfEmpty(superType); List<JType> subTypes = generateDeductionBasedSubTypes(nodeName, arrayNode, objects, superType, _package); annotateWithDeductionBasedSubtypes(superType, subTypes); } else { ruleFactory.getLogger().error("No way to deduct object deserialization target through required properties: " + nodeName); return null; } objectsSuperType = superType; } } Map<String, JClass> generatedTypes = new LinkedHashMap<>(); for (Map.Entry<String, List<ResolvedType>> listEntry : resolved.entrySet()) { if (listEntry.getKey().equals("object")) { generatedTypes.put("object", objectsSuperType); } else { generatedTypes.put(listEntry.getKey(), (JClass)listEntry.getValue().get(0).generate(ruleFactory, nodeName, arrayNode, wrapperClass)); } } if (wrapperClass != null) { if (generatedTypes.size() == 2 && generatedTypes.get("array") != null) { JType arrayType = generatedTypes.get("array"); Pair<JType, JClass> arrayItemType = unpackArrayItemClass(arrayType); if (arrayItemType != null) { Map.Entry<String, List<ResolvedType>> entry = resolved.entrySet().stream() .filter(e -> !e.getKey().equals("array")).findFirst().orElseThrow(); JType itemType; if (entry.getKey().equals("object")) { itemType = objectsSuperType; } else { itemType = entry.getValue().get(0).generate(ruleFactory, nodeName, arrayNode, wrapperClass); } if (itemType != null && itemType.equals(arrayItemType.getRight())) { generateDeserializeIntoArray(wrapperClass, entry.getKey(), arrayItemType, lenientDeserialize); return wrapperClass; } } } generateDeserializeIntoValueProperty(wrapperClass, generatedTypes, node); return wrapperClass; } return schema.getJavaType(); }