From 801c8ed8ac7640ef733db0274d7352693ea73757 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 15 Sep 2020 09:41:14 +0200 Subject: [PATCH] Revise type resolution for alignment with AbstractJsonHttpMessageConverter See gh-21188 --- ...SerializationJsonHttpMessageConverter.java | 59 +++++++++++-------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java index 8db1830fa18..96e21d605d7 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java @@ -27,6 +27,7 @@ import kotlinx.serialization.SerializationException; import kotlinx.serialization.SerializersKt; import kotlinx.serialization.json.Json; +import org.springframework.core.GenericTypeResolver; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -46,6 +47,7 @@ import org.springframework.util.StreamUtils; * * @author Andreas Ahlenstorf * @author Sebastien Deleuze + * @author Juergen Hoeller * @since 5.3 */ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGenericHttpMessageConverter { @@ -56,6 +58,7 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric private final Json json; + /** * Construct a new {@code KotlinSerializationJsonHttpMessageConverter} with the default configuration. */ @@ -71,10 +74,11 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric this.json = json; } + @Override protected boolean supports(Class clazz) { try { - resolve(clazz); + serializer(clazz); return true; } catch (Exception ex) { @@ -83,17 +87,27 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric } @Override - protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - return this.read(clazz, null, inputMessage); + public final Object read(Type type, @Nullable Class contextClass, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + + return decode(serializer(GenericTypeResolver.resolveType(type, contextClass)), inputMessage); } @Override - public Object read(Type type, @Nullable Class contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { + protected final Object readInternal(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + + return decode(serializer(clazz), inputMessage); + } + + private Object decode(KSerializer serializer, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + MediaType contentType = inputMessage.getHeaders().getContentType(); String jsonText = StreamUtils.copyToString(inputMessage.getBody(), getCharsetToUse(contentType)); try { // TODO Use stream based API when available - return this.json.decodeFromString(resolve(type), jsonText); + return this.json.decodeFromString(serializer, jsonText); } catch (SerializationException ex) { throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex, inputMessage); @@ -101,19 +115,17 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric } @Override - protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws HttpMessageNotWritableException { - try { - this.writeInternal(o, o.getClass(), outputMessage); - } - catch (IOException ex) { - throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex); - } + protected final void writeInternal(Object object, @Nullable Type type, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + + encode(object, serializer(type != null ? type : object.getClass()), outputMessage); } - @Override - protected void writeInternal(Object o, @Nullable Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { + private void encode(Object object, KSerializer serializer, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + try { - String json = this.json.encodeToString(resolve(type), o); + String json = this.json.encodeToString(serializer, object); MediaType contentType = outputMessage.getHeaders().getContentType(); outputMessage.getBody().write(json.getBytes(getCharsetToUse(contentType))); outputMessage.getBody().flush(); @@ -134,16 +146,14 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric } /** - * Tries to find a serializer that can marshall or unmarshall instances of the given type using - * kotlinx.serialization. If no serializer can be found, an exception is thrown. - *

- * Resolved serializers are cached and cached results are returned on successive calls. - * - * @param type to find a serializer for. - * @return resolved serializer for the given type. - * @throws RuntimeException if no serializer supporting the given type can be found. + * Tries to find a serializer that can marshall or unmarshall instances of the given type + * using kotlinx.serialization. If no serializer can be found, an exception is thrown. + *

Resolved serializers are cached and cached results are returned on successive calls. + * @param type the type to find a serializer for + * @return a resolved serializer for the given type + * @throws RuntimeException if no serializer supporting the given type can be found */ - private KSerializer resolve(Type type) { + private KSerializer serializer(Type type) { KSerializer serializer = serializerCache.get(type); if (serializer == null) { serializer = SerializersKt.serializer(type); @@ -151,4 +161,5 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric } return serializer; } + }