/** * Resolves actual type to be used for resource deserialization. * <p> * If user provides class with type annotation that is equal to the type value in response data, same class * will be used. If provided class is super type of actual class that is resolved using response type value, * subclass will be returned. This allows for deserializing responses in use cases where one of many subtypes * can be returned by the server and user is not sure which one will it be. * </p> * @param object JSON object containing type value * @param userType provided user type * @return {@link Class} */ private Class<?> getActualType(JsonNode object, Class<?> userType) { String type = object.get(TYPE).asText(); String definedTypeName = configuration.getTypeName(userType); if (definedTypeName != null && definedTypeName.equals(type)) { return userType; } else { Class<?> actualType = configuration.getTypeClass(type); if (actualType != null && userType.isAssignableFrom(actualType)) { return actualType; } } throw new UnregisteredTypeException(type); }
/** * Parses out included resources excluding relationships. * @param parent root node * @return map of identifier/resource pairs * @throws IOException * @throws IllegalAccessException * @throws InstantiationException */ private Map<String, Object> getIncludedResources(JsonNode parent) throws IOException, IllegalAccessException, InstantiationException { Map<String, Object> result = new HashMap<>(); if (parent.has(INCLUDED)) { for (JsonNode jsonNode : parent.get(INCLUDED)) { String type = jsonNode.get(TYPE).asText(); Class<?> clazz = configuration.getTypeClass(type); if (clazz != null) { Object object = readObject(jsonNode, clazz, false); if (object != null) { result.put(createIdentifier(jsonNode), object); } } else if (!deserializationFeatures.contains(DeserializationFeature.ALLOW_UNKNOWN_INCLUSIONS)) { throw new IllegalArgumentException("Included section contains unknown resource type: " + type); } } } return result; }
/** * Parses out included resources excluding relationships. * @param parent root node * @return map of identifier/resource pairs * @throws IOException * @throws IllegalAccessException * @throws InstantiationException */ private Map<String, Object> getIncludedResources(JsonNode parent) throws IOException, IllegalAccessException, InstantiationException { Map<String, Object> result = new HashMap<>(); if (parent.has(INCLUDED)) { for (JsonNode jsonNode : parent.get(INCLUDED)) { String type = jsonNode.get(TYPE).asText(); Class<?> clazz = configuration.getTypeClass(type); if (clazz != null) { Object object = readObject(jsonNode, clazz, false); if (object != null) { result.put(createIdentifier(jsonNode), object); } } else if (!deserializationFeatures.contains(DeserializationFeature.ALLOW_UNKNOWN_INCLUSIONS)) { throw new IllegalArgumentException("Included section contains unknown resource type: " + type); } } } return result; }
/** * Resolves actual type to be used for resource deserialization. * <p> * If user provides class with type annotation that is equal to the type value in response data, same class * will be used. If provided class is super type of actual class that is resolved using response type value, * subclass will be returned. This allows for deserializing responses in use cases where one of many subtypes * can be returned by the server and user is not sure which one will it be. * </p> * @param object JSON object containing type value * @param userType provided user type * @return {@link Class} */ private Class<?> getActualType(JsonNode object, Class<?> userType) { String type = object.get(TYPE).asText(); String definedTypeName = configuration.getTypeName(userType); if (definedTypeName != null && definedTypeName.equals(type)) { return userType; } else { Class<?> actualType = configuration.getTypeClass(type); if (actualType != null && userType.isAssignableFrom(actualType)) { return actualType; } } throw new UnregisteredTypeException(type); }