Revise type resolution for alignment with AbstractJsonHttpMessageConverter
See gh-21188
This commit is contained in:
parent
cd6085a310
commit
801c8ed8ac
|
|
@ -27,6 +27,7 @@ import kotlinx.serialization.SerializationException;
|
||||||
import kotlinx.serialization.SerializersKt;
|
import kotlinx.serialization.SerializersKt;
|
||||||
import kotlinx.serialization.json.Json;
|
import kotlinx.serialization.json.Json;
|
||||||
|
|
||||||
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.http.HttpInputMessage;
|
import org.springframework.http.HttpInputMessage;
|
||||||
import org.springframework.http.HttpOutputMessage;
|
import org.springframework.http.HttpOutputMessage;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
@ -46,6 +47,7 @@ import org.springframework.util.StreamUtils;
|
||||||
*
|
*
|
||||||
* @author Andreas Ahlenstorf
|
* @author Andreas Ahlenstorf
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
public class KotlinSerializationJsonHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
|
public class KotlinSerializationJsonHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
|
||||||
|
|
@ -56,6 +58,7 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
|
|
||||||
private final Json json;
|
private final Json json;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new {@code KotlinSerializationJsonHttpMessageConverter} with the default configuration.
|
* Construct a new {@code KotlinSerializationJsonHttpMessageConverter} with the default configuration.
|
||||||
*/
|
*/
|
||||||
|
|
@ -71,10 +74,11 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
this.json = json;
|
this.json = json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean supports(Class<?> clazz) {
|
protected boolean supports(Class<?> clazz) {
|
||||||
try {
|
try {
|
||||||
resolve(clazz);
|
serializer(clazz);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
|
@ -83,17 +87,27 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
|
public final Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)
|
||||||
return this.read(clazz, null, inputMessage);
|
throws IOException, HttpMessageNotReadableException {
|
||||||
|
|
||||||
|
return decode(serializer(GenericTypeResolver.resolveType(type, contextClass)), inputMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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<Object> serializer, HttpInputMessage inputMessage)
|
||||||
|
throws IOException, HttpMessageNotReadableException {
|
||||||
|
|
||||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||||
String jsonText = StreamUtils.copyToString(inputMessage.getBody(), getCharsetToUse(contentType));
|
String jsonText = StreamUtils.copyToString(inputMessage.getBody(), getCharsetToUse(contentType));
|
||||||
try {
|
try {
|
||||||
// TODO Use stream based API when available
|
// TODO Use stream based API when available
|
||||||
return this.json.decodeFromString(resolve(type), jsonText);
|
return this.json.decodeFromString(serializer, jsonText);
|
||||||
}
|
}
|
||||||
catch (SerializationException ex) {
|
catch (SerializationException ex) {
|
||||||
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex, inputMessage);
|
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex, inputMessage);
|
||||||
|
|
@ -101,19 +115,17 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws HttpMessageNotWritableException {
|
protected final void writeInternal(Object object, @Nullable Type type, HttpOutputMessage outputMessage)
|
||||||
try {
|
throws IOException, HttpMessageNotWritableException {
|
||||||
this.writeInternal(o, o.getClass(), outputMessage);
|
|
||||||
}
|
encode(object, serializer(type != null ? type : object.getClass()), outputMessage);
|
||||||
catch (IOException ex) {
|
|
||||||
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void encode(Object object, KSerializer<Object> serializer, HttpOutputMessage outputMessage)
|
||||||
protected void writeInternal(Object o, @Nullable Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
|
throws IOException, HttpMessageNotWritableException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String json = this.json.encodeToString(resolve(type), o);
|
String json = this.json.encodeToString(serializer, object);
|
||||||
MediaType contentType = outputMessage.getHeaders().getContentType();
|
MediaType contentType = outputMessage.getHeaders().getContentType();
|
||||||
outputMessage.getBody().write(json.getBytes(getCharsetToUse(contentType)));
|
outputMessage.getBody().write(json.getBytes(getCharsetToUse(contentType)));
|
||||||
outputMessage.getBody().flush();
|
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
|
* Tries to find a serializer that can marshall or unmarshall instances of the given type
|
||||||
* kotlinx.serialization. If no serializer can be found, an exception is thrown.
|
* using kotlinx.serialization. If no serializer can be found, an exception is thrown.
|
||||||
* <p>
|
* <p>Resolved serializers are cached and cached results are returned on successive calls.
|
||||||
* 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
|
||||||
* @param type to find a serializer for.
|
* @throws RuntimeException if no serializer supporting the given type can be found
|
||||||
* @return resolved serializer for the given type.
|
|
||||||
* @throws RuntimeException if no serializer supporting the given type can be found.
|
|
||||||
*/
|
*/
|
||||||
private KSerializer<Object> resolve(Type type) {
|
private KSerializer<Object> serializer(Type type) {
|
||||||
KSerializer<Object> serializer = serializerCache.get(type);
|
KSerializer<Object> serializer = serializerCache.get(type);
|
||||||
if (serializer == null) {
|
if (serializer == null) {
|
||||||
serializer = SerializersKt.serializer(type);
|
serializer = SerializersKt.serializer(type);
|
||||||
|
|
@ -151,4 +161,5 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
}
|
}
|
||||||
return serializer;
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue