@@ -22,9 +22,9 @@ namespace System.Net.Http.Formatting
22
22
/// </summary>
23
23
public class JsonMediaTypeFormatter : BaseJsonMediaTypeFormatter
24
24
{
25
- private ConcurrentDictionary < Type , DataContractJsonSerializer > _dataContractSerializerCache = new ConcurrentDictionary < Type , DataContractJsonSerializer > ( ) ;
26
- private XmlDictionaryReaderQuotas _readerQuotas = FormattingUtilities . CreateDefaultReaderQuotas ( ) ;
27
- private RequestHeaderMapping _requestHeaderMapping ;
25
+ private readonly ConcurrentDictionary < Type , DataContractJsonSerializer > _dataContractSerializerCache = new ConcurrentDictionary < Type , DataContractJsonSerializer > ( ) ;
26
+ private readonly XmlDictionaryReaderQuotas _readerQuotas = FormattingUtilities . CreateDefaultReaderQuotas ( ) ;
27
+ private readonly RequestHeaderMapping _requestHeaderMapping ;
28
28
29
29
/// <summary>
30
30
/// Initializes a new instance of the <see cref="JsonMediaTypeFormatter"/> class.
@@ -216,17 +216,23 @@ public override object ReadFromStream(Type type, Stream readStream, Encoding eff
216
216
{
217
217
DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer ( type ) ;
218
218
219
- #if NETFX_CORE // JsonReaderWriterFactory is internal in netstandard1.3. Unfortunately, ignoring _readerQuotas.
220
- // Force a preamble into the stream since DataContractJsonSerializer only supports auto-detecting
221
- // encoding in netstandard1.3 ].
222
- readStream = new ReadOnlyStreamWithEncodingPreamble ( readStream , effectiveEncoding ) ;
219
+ // JsonReaderWriterFactory is internal, CreateTextReader only supports auto-detecting the encoding
220
+ // and auto-detection fails in some cases for the NETFX_CORE project. In addition, DCS encodings are
221
+ // limited to UTF8, UTF16BE, and UTF16LE. Convert to UTF8 as we read.
222
+ Stream innerStream = string . Equals ( effectiveEncoding . WebName , Utf8Encoding . WebName , StringComparison . OrdinalIgnoreCase ) ?
223
+ new NonClosingDelegatingStream ( readStream ) :
224
+ new TranscodingStream ( readStream , effectiveEncoding , Utf8Encoding , leaveOpen : true ) ;
223
225
224
- return dataContractSerializer . ReadObject ( new NonClosingDelegatingStream ( readStream ) ) ;
225
- #else
226
- using ( XmlReader reader = JsonReaderWriterFactory . CreateJsonReader ( new NonClosingDelegatingStream ( readStream ) , effectiveEncoding , _readerQuotas , null ) )
226
+ #if NETFX_CORE
227
+ using ( innerStream )
227
228
{
228
- return dataContractSerializer . ReadObject ( reader ) ;
229
+ // Unfortunately, we're ignoring _readerQuotas.
230
+ return dataContractSerializer . ReadObject ( innerStream ) ;
229
231
}
232
+ #else
233
+ // XmlReader will always dispose of innerStream when we dispose of the reader.
234
+ using var reader = JsonReaderWriterFactory . CreateJsonReader ( innerStream , Utf8Encoding , _readerQuotas , onClose : null ) ;
235
+ return dataContractSerializer . ReadObject ( reader ) ;
230
236
#endif
231
237
}
232
238
else
@@ -277,14 +283,6 @@ public override void WriteToStream(Type type, object value, Stream writeStream,
277
283
278
284
if ( UseDataContractJsonSerializer )
279
285
{
280
- #if NETFX_CORE // DataContractJsonSerializer writes only UTF8 in netstandard1.3. Later versions of (now public)
281
- // JsonReaderWriterFactory can compensate.
282
- if ( ! string . Equals ( Encoding . UTF8 . WebName , effectiveEncoding . WebName , StringComparison . OrdinalIgnoreCase ) )
283
- {
284
- throw new NotSupportedException ( "!!! To be added !!!" ) ;
285
- }
286
- #endif
287
-
288
286
if ( MediaTypeFormatter . TryGetDelegatingTypeForIQueryableGenericOrSame ( ref type ) )
289
287
{
290
288
if ( value != null )
@@ -293,23 +291,39 @@ public override void WriteToStream(Type type, object value, Stream writeStream,
293
291
}
294
292
}
295
293
296
- DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer ( type ) ;
297
-
298
- #if NETFX_CORE // JsonReaderWriterFactory is internal in netstandard1.3.
299
- dataContractSerializer . WriteObject ( writeStream , value ) ;
300
- #else
301
- using ( XmlWriter writer = JsonReaderWriterFactory . CreateJsonWriter ( writeStream , effectiveEncoding , ownsStream : false ) )
294
+ WritePreamble ( writeStream , effectiveEncoding ) ;
295
+ if ( string . Equals ( effectiveEncoding . WebName , Utf8Encoding . WebName , StringComparison . OrdinalIgnoreCase ) )
302
296
{
303
- dataContractSerializer . WriteObject ( writer , value ) ;
297
+ WriteObject ( writeStream , type , value ) ;
298
+ }
299
+ else
300
+ {
301
+ // JsonReaderWriterFactory is internal and DataContractJsonSerializer only writes UTF8 for the
302
+ // NETFX_CORE project. In addition, DCS encodings are limited to UTF8, UTF16BE, and UTF16LE.
303
+ // Convert to UTF8 as we write.
304
+ using var innerStream = new TranscodingStream ( writeStream , effectiveEncoding , Utf8Encoding , leaveOpen : true ) ;
305
+ WriteObject ( innerStream , type , value ) ;
304
306
}
305
- #endif
306
307
}
307
308
else
308
309
{
309
310
base . WriteToStream ( type , value , writeStream , effectiveEncoding ) ;
310
311
}
311
312
}
312
313
314
+ private void WriteObject ( Stream stream , Type type , object value )
315
+ {
316
+ DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer ( type ) ;
317
+
318
+ // Do not dispose of the stream. WriteToStream handles that where it's needed.
319
+ #if NETFX_CORE
320
+ dataContractSerializer . WriteObject ( stream , value ) ;
321
+ #else
322
+ using XmlWriter writer = JsonReaderWriterFactory . CreateJsonWriter ( stream , Utf8Encoding , ownsStream : false ) ;
323
+ dataContractSerializer . WriteObject ( writer , value ) ;
324
+ #endif
325
+ }
326
+
313
327
[ SuppressMessage ( "Microsoft.Design" , "CA1031:DoNotCatchGeneralExceptionTypes" , Justification = "Catch all is around an extensibile method" ) ]
314
328
private DataContractJsonSerializer CreateDataContractSerializer ( Type type , bool throwOnError )
315
329
{
0 commit comments