Skip to content

Commit

Permalink
Change how JavaType is resolved to support JsonSerializable better (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
alzimmermsft authored May 10, 2024
1 parent 47b1085 commit e7deb7b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import com.azure.core.annotation.HeaderCollection;
import com.azure.core.http.HttpHeader;
import com.azure.core.http.HttpHeaders;
import com.azure.core.implementation.ReflectiveInvoker;
import com.azure.core.implementation.ReflectionSerializable;
import com.azure.core.implementation.ReflectionUtils;
import com.azure.core.implementation.ReflectiveInvoker;
import com.azure.core.implementation.TypeUtil;
import com.azure.core.util.logging.ClientLogger;
import com.azure.json.JsonSerializable;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -264,6 +266,7 @@ public JsonNode readTree(byte[] content) throws IOException {
}
}

@SuppressWarnings("unchecked")
private JavaType createJavaType(Type type) {
if (type == null) {
return null;
Expand All @@ -280,7 +283,28 @@ private JavaType createJavaType(Type type) {
return getFromTypeCache(type, t -> mapper.getTypeFactory()
.constructParametricType((Class<?>) parameterizedType.getRawType(), javaTypeArguments));
} else {
return getFromTypeCache(type, t -> mapper.getTypeFactory().constructType(t));
return getFromTypeCache(type, t -> {
JavaType javaType = mapper.constructType(t);

// Need additional handling here so that the JavaType returned has the correct value handler for
// JsonSerializable types.
// While JsonSerializableDeserializer is registered with the ObjectMapper, and it mutates the
// JsonSerializer used by Jackson to handle as a JsonSerializable type, there have been cases where
// collection types (List, Map, etc) have not been handled correctly. So, additional handling is done
// here to ensure that the JavaType returned has the correct value handler.

if (!(t instanceof Class<?>)) {
// Not a Class, so can't be a JsonSerializable type.
return javaType;
}

if (ReflectionSerializable.supportsJsonSerializable((Class<?>) t)) {
// JsonSerializable type, so add the JsonSerializableDeserializer as the value handler.
return javaType.withValueHandler(new JsonSerializableDeserializer((Class<JsonSerializable<?>>) t));
}

return javaType;
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
import com.azure.core.annotation.HeaderCollection;
import com.azure.core.http.HttpHeader;
import com.azure.core.http.HttpHeaders;
import com.azure.core.implementation.ReflectionSerializable;
import com.azure.core.implementation.ReflectionUtils;
import com.azure.core.implementation.ReflectiveInvoker;
import com.azure.core.implementation.TypeUtil;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LogLevel;
import com.azure.core.util.serializer.MemberNameConverter;
import com.azure.json.JsonSerializable;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -294,6 +296,7 @@ public JsonNode readTree(byte[] content) throws IOException {
}
}

@SuppressWarnings("unchecked")
private JavaType createJavaType(Type type) {
if (type == null) {
return null;
Expand All @@ -310,7 +313,28 @@ private JavaType createJavaType(Type type) {
return getFromTypeCache(type, t -> mapper.getTypeFactory()
.constructParametricType((Class<?>) parameterizedType.getRawType(), javaTypeArguments));
} else {
return getFromTypeCache(type, t -> mapper.getTypeFactory().constructType(t));
return getFromTypeCache(type, t -> {
JavaType javaType = mapper.constructType(t);

// Need additional handling here so that the JavaType returned has the correct value handler for
// JsonSerializable types.
// While JsonSerializableDeserializer is registered with the ObjectMapper, and it mutates the
// JsonSerializer used by Jackson to handle as a JsonSerializable type, there have been cases where
// collection types (List, Map, etc) have not been handled correctly. So, additional handling is done
// here to ensure that the JavaType returned has the correct value handler.

if (!(t instanceof Class<?>)) {
// Not a Class, so can't be a JsonSerializable type.
return javaType;
}

if (ReflectionSerializable.supportsJsonSerializable((Class<?>) t)) {
// JsonSerializable type, so add the JsonSerializableDeserializer as the value handler.
return javaType.withValueHandler(new JsonSerializableDeserializer((Class<JsonSerializable<?>>) t));
}

return javaType;
});
}
}

Expand Down

0 comments on commit e7deb7b

Please sign in to comment.