27
27
import kotlinx .serialization .SerializersKt ;
28
28
import kotlinx .serialization .json .Json ;
29
29
30
+ import org .springframework .core .GenericTypeResolver ;
30
31
import org .springframework .http .HttpInputMessage ;
31
32
import org .springframework .http .HttpOutputMessage ;
32
33
import org .springframework .http .MediaType ;
46
47
*
47
48
* @author Andreas Ahlenstorf
48
49
* @author Sebastien Deleuze
50
+ * @author Juergen Hoeller
49
51
* @since 5.3
50
52
*/
51
53
public class KotlinSerializationJsonHttpMessageConverter extends AbstractGenericHttpMessageConverter <Object > {
@@ -56,6 +58,7 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
56
58
57
59
private final Json json ;
58
60
61
+
59
62
/**
60
63
* Construct a new {@code KotlinSerializationJsonHttpMessageConverter} with the default configuration.
61
64
*/
@@ -71,10 +74,11 @@ public KotlinSerializationJsonHttpMessageConverter(Json json) {
71
74
this .json = json ;
72
75
}
73
76
77
+
74
78
@ Override
75
79
protected boolean supports (Class <?> clazz ) {
76
80
try {
77
- resolve (clazz );
81
+ serializer (clazz );
78
82
return true ;
79
83
}
80
84
catch (Exception ex ) {
@@ -83,37 +87,45 @@ protected boolean supports(Class<?> clazz) {
83
87
}
84
88
85
89
@ Override
86
- protected Object readInternal (Class <?> clazz , HttpInputMessage inputMessage ) throws IOException , HttpMessageNotReadableException {
87
- return this .read (clazz , null , inputMessage );
90
+ public final Object read (Type type , @ Nullable Class <?> contextClass , HttpInputMessage inputMessage )
91
+ throws IOException , HttpMessageNotReadableException {
92
+
93
+ return decode (serializer (GenericTypeResolver .resolveType (type , contextClass )), inputMessage );
88
94
}
89
95
90
96
@ Override
91
- public Object read (Type type , @ Nullable Class <?> contextClass , HttpInputMessage inputMessage ) throws IOException , HttpMessageNotReadableException {
97
+ protected final Object readInternal (Class <?> clazz , HttpInputMessage inputMessage )
98
+ throws IOException , HttpMessageNotReadableException {
99
+
100
+ return decode (serializer (clazz ), inputMessage );
101
+ }
102
+
103
+ private Object decode (KSerializer <Object > serializer , HttpInputMessage inputMessage )
104
+ throws IOException , HttpMessageNotReadableException {
105
+
92
106
MediaType contentType = inputMessage .getHeaders ().getContentType ();
93
107
String jsonText = StreamUtils .copyToString (inputMessage .getBody (), getCharsetToUse (contentType ));
94
108
try {
95
109
// TODO Use stream based API when available
96
- return this .json .decodeFromString (resolve ( type ) , jsonText );
110
+ return this .json .decodeFromString (serializer , jsonText );
97
111
}
98
112
catch (SerializationException ex ) {
99
113
throw new HttpMessageNotReadableException ("Could not read JSON: " + ex .getMessage (), ex , inputMessage );
100
114
}
101
115
}
102
116
103
117
@ Override
104
- protected void writeInternal (Object o , HttpOutputMessage outputMessage ) throws HttpMessageNotWritableException {
105
- try {
106
- this .writeInternal (o , o .getClass (), outputMessage );
107
- }
108
- catch (IOException ex ) {
109
- throw new HttpMessageNotWritableException ("Could not write JSON: " + ex .getMessage (), ex );
110
- }
118
+ protected final void writeInternal (Object object , @ Nullable Type type , HttpOutputMessage outputMessage )
119
+ throws IOException , HttpMessageNotWritableException {
120
+
121
+ encode (object , serializer (type != null ? type : object .getClass ()), outputMessage );
111
122
}
112
123
113
- @ Override
114
- protected void writeInternal (Object o , @ Nullable Type type , HttpOutputMessage outputMessage ) throws IOException , HttpMessageNotWritableException {
124
+ private void encode (Object object , KSerializer <Object > serializer , HttpOutputMessage outputMessage )
125
+ throws IOException , HttpMessageNotWritableException {
126
+
115
127
try {
116
- String json = this .json .encodeToString (resolve ( type ), o );
128
+ String json = this .json .encodeToString (serializer , object );
117
129
MediaType contentType = outputMessage .getHeaders ().getContentType ();
118
130
outputMessage .getBody ().write (json .getBytes (getCharsetToUse (contentType )));
119
131
outputMessage .getBody ().flush ();
@@ -134,21 +146,20 @@ private Charset getCharsetToUse(@Nullable MediaType contentType) {
134
146
}
135
147
136
148
/**
137
- * Tries to find a serializer that can marshall or unmarshall instances of the given type using
138
- * kotlinx.serialization. If no serializer can be found, an exception is thrown.
139
- * <p>
140
- * Resolved serializers are cached and cached results are returned on successive calls.
141
- *
142
- * @param type to find a serializer for.
143
- * @return resolved serializer for the given type.
144
- * @throws RuntimeException if no serializer supporting the given type can be found.
149
+ * Tries to find a serializer that can marshall or unmarshall instances of the given type
150
+ * using kotlinx.serialization. If no serializer can be found, an exception is thrown.
151
+ * <p>Resolved serializers are cached and cached results are returned on successive calls.
152
+ * @param type the type to find a serializer for
153
+ * @return a resolved serializer for the given type
154
+ * @throws RuntimeException if no serializer supporting the given type can be found
145
155
*/
146
- private KSerializer <Object > resolve (Type type ) {
156
+ private KSerializer <Object > serializer (Type type ) {
147
157
KSerializer <Object > serializer = serializerCache .get (type );
148
158
if (serializer == null ) {
149
159
serializer = SerializersKt .serializer (type );
150
160
serializerCache .put (type , serializer );
151
161
}
152
162
return serializer ;
153
163
}
164
+
154
165
}
0 commit comments