[release/6.0-rc1] Align DCJS with 4.8 implementation. (#57883)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 24 Aug 2021 06:35:54 +0000 (08:35 +0200)
committerGitHub <noreply@github.com>
Tue, 24 Aug 2021 06:35:54 +0000 (08:35 +0200)
* Align DCJS with 4.8 version. This work addresses #55270.

* Close() nits.

* Remove some extraneous trimmer attributes.

* Another trimmer nit.

Co-authored-by: Steve Molloy <smolloy@microsoft.com>
16 files changed:
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ReflectionJsonFormatWriter.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonReader.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializerContext.cs
src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs
src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.RuntimeOnly.cs

index 74f4d0c..30d2ded 100644 (file)
@@ -20,30 +20,25 @@ namespace System.Runtime.Serialization.Json
 
     public sealed class DataContractJsonSerializer : XmlObjectSerializer
     {
-        private const char BACK_SLASH = '\\';
-        private const char FORWARD_SLASH = '/';
-        private const char HIGH_SURROGATE_START = (char)0xd800;
-        private const char LOW_SURROGATE_END = (char)0xdfff;
-        private const char MAX_CHAR = (char)0xfffe;
-        private const char WHITESPACE = ' ';
-
-
         internal IList<Type>? knownTypeList;
         internal DataContractDictionary? knownDataContracts;
-        private readonly EmitTypeInformation _emitTypeInformation;
+        private EmitTypeInformation _emitTypeInformation;
         private ReadOnlyCollection<Type>? _knownTypeCollection;
-        private readonly int _maxItemsInObjectGraph;
-        private readonly bool _serializeReadOnlyTypes;
-        private readonly DateTimeFormat? _dateTimeFormat;
-        private readonly bool _useSimpleDictionaryFormat;
+        private int _maxItemsInObjectGraph;
+        private bool _serializeReadOnlyTypes;
+        private DateTimeFormat? _dateTimeFormat;
+        private bool _useSimpleDictionaryFormat;
+        private bool _ignoreExtensionDataObject;
+        private DataContract? _rootContract; // post-surrogate
+        private XmlDictionaryString? _rootName;
+        private bool _rootNameRequiresMapping;
+        private Type _rootType;
 
-        private readonly DataContractJsonSerializerImpl _serializer;
-        private readonly bool _ignoreExtensionDataObject;
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         public DataContractJsonSerializer(Type type)
+            : this(type, (IEnumerable<Type>?)null)
         {
-            _serializer = new DataContractJsonSerializerImpl(type);
         }
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -60,8 +55,8 @@ namespace System.Runtime.Serialization.Json
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         public DataContractJsonSerializer(Type type, IEnumerable<Type>? knownTypes)
+            : this(type, null, knownTypes, int.MaxValue, false, false)
         {
-            _serializer = new DataContractJsonSerializerImpl(type, knownTypes);
         }
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -72,478 +67,25 @@ namespace System.Runtime.Serialization.Json
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         public DataContractJsonSerializer(Type type, XmlDictionaryString? rootName, IEnumerable<Type>? knownTypes)
+            : this(type, rootName, knownTypes, int.MaxValue, false, false)
         {
-            _serializer = new DataContractJsonSerializerImpl(type, rootName, knownTypes);
         }
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         public DataContractJsonSerializer(Type type, DataContractJsonSerializerSettings? settings)
         {
-            _serializer = new DataContractJsonSerializerImpl(type, settings);
-        }
-
-        public bool IgnoreExtensionDataObject
-        {
-            get { return _ignoreExtensionDataObject; }
-        }
-
-        public ReadOnlyCollection<Type> KnownTypes
-        {
-            get
-            {
-                if (_knownTypeCollection == null)
-                {
-                    if (knownTypeList != null)
-                    {
-                        _knownTypeCollection = new ReadOnlyCollection<Type>(knownTypeList);
-                    }
-                    else
-                    {
-                        _knownTypeCollection = new ReadOnlyCollection<Type>(Type.EmptyTypes);
-                    }
-                }
-                return _knownTypeCollection;
-            }
-        }
-
-        internal override DataContractDictionary? KnownDataContracts
-        {
-            [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-            get
-            {
-                if (this.knownDataContracts == null && this.knownTypeList != null)
-                {
-                    // This assignment may be performed concurrently and thus is a race condition.
-                    // It's safe, however, because at worse a new (and identical) dictionary of
-                    // data contracts will be created and re-assigned to this field.  Introduction
-                    // of a lock here could lead to deadlocks.
-                    this.knownDataContracts = XmlObjectSerializerContext.GetDataContractsForKnownTypes(this.knownTypeList);
-                }
-                return this.knownDataContracts;
-            }
-        }
-
-        public int MaxItemsInObjectGraph
-        {
-            get { return _maxItemsInObjectGraph; }
-        }
-
-        public DateTimeFormat? DateTimeFormat
-        {
-            get
-            {
-                return _dateTimeFormat;
-            }
-        }
-
-        public EmitTypeInformation EmitTypeInformation
-        {
-            get
-            {
-                return _emitTypeInformation;
-            }
-        }
-
-        public bool SerializeReadOnlyTypes
-        {
-            get
-            {
-                return _serializeReadOnlyTypes;
-            }
-        }
-
-
-        public bool UseSimpleDictionaryFormat
-        {
-            get
-            {
-                return _useSimpleDictionaryFormat;
-            }
-        }
-
-        internal static void CheckIfTypeIsReference(DataContract dataContract)
-        {
-            if (dataContract.IsReference)
-            {
-                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
-                    XmlObjectSerializer.CreateSerializationException(SR.Format(
-                        SR.JsonUnsupportedForIsReference,
-                        DataContract.GetClrTypeFullName(dataContract.UnderlyingType),
-                        dataContract.IsReference)));
-            }
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        internal static DataContract GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType)
-        {
-            DataContract contract = DataContractSerializer.GetDataContract(declaredTypeContract, declaredType, objectType);
-            CheckIfTypeIsReference(contract);
-            return contract;
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteObject(Stream stream, object? graph)
-        {
-            _serializer.WriteObject(stream, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteObject(XmlWriter writer, object? graph)
-        {
-            _serializer.WriteObject(writer, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteObject(XmlDictionaryWriter writer, object? graph)
-        {
-            _serializer.WriteObject(writer, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override object? ReadObject(Stream stream)
-        {
-            return _serializer.ReadObject(stream);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override object? ReadObject(XmlReader reader)
-        {
-            return _serializer.ReadObject(reader);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override object? ReadObject(XmlReader reader, bool verifyObjectName)
-        {
-            return _serializer.ReadObject(reader, verifyObjectName);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override object? ReadObject(XmlDictionaryReader reader)
-        {
-            return _serializer.ReadObject(reader);
-        }
-
-        private List<Type> GetKnownTypesFromContext(XmlObjectSerializerContext context, IList<Type>? serializerKnownTypeList)
-        {
-            List<Type> knownTypesList = new List<Type>();
-            if (context != null)
-            {
-                List<XmlQualifiedName> stableNames = new List<XmlQualifiedName>();
-                Dictionary<XmlQualifiedName, DataContract>[] entries = context.scopedKnownTypes.dataContractDictionaries;
-                if (entries != null)
-                {
-                    for (int i = 0; i < entries.Length; i++)
-                    {
-                        Dictionary<XmlQualifiedName, DataContract> entry = entries[i];
-                        if (entry != null)
-                        {
-                            foreach (KeyValuePair<XmlQualifiedName, DataContract> pair in entry)
-                            {
-                                if (!stableNames.Contains(pair.Key))
-                                {
-                                    stableNames.Add(pair.Key);
-                                    knownTypesList.Add(pair.Value.UnderlyingType);
-                                }
-                            }
-                        }
-                    }
-                }
-                if (serializerKnownTypeList != null)
-                {
-                    knownTypesList.AddRange(serializerKnownTypeList);
-                }
-            }
-            return knownTypesList;
-        }
-
-        internal static void InvokeOnSerializing(object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context)
-        {
-            if (contract is ClassDataContract classContract)
-            {
-                if (classContract.BaseContract != null)
-                    InvokeOnSerializing(value, classContract.BaseContract, context);
-                if (classContract.OnSerializing != null)
-                {
-                    bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null);
-                    try
-                    {
-                        classContract.OnSerializing.Invoke(value, new object[] { context.GetStreamingContext() });
-                    }
-                    catch (SecurityException securityException)
-                    {
-                        if (memberAccessFlag)
-                        {
-                            classContract.RequiresMemberAccessForWrite(securityException);
-                        }
-                        else
-                        {
-                            throw;
-                        }
-                    }
-                    catch (TargetInvocationException targetInvocationException)
-                    {
-                        if (targetInvocationException.InnerException == null)
-                            throw;
-                        //We are catching the TIE here and throws the inner exception only,
-                        //this is needed to have a consistent exception story in all serializers
-                        throw targetInvocationException.InnerException;
-                    }
-                }
-            }
-        }
-
-        internal static void InvokeOnSerialized(object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context)
-        {
-            if (contract is ClassDataContract classContract)
-            {
-                if (classContract.BaseContract != null)
-                    InvokeOnSerialized(value, classContract.BaseContract, context);
-                if (classContract.OnSerialized != null)
-                {
-                    bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null);
-                    try
-                    {
-                        classContract.OnSerialized.Invoke(value, new object[] { context.GetStreamingContext() });
-                    }
-                    catch (SecurityException securityException)
-                    {
-                        if (memberAccessFlag)
-                        {
-                            classContract.RequiresMemberAccessForWrite(securityException);
-                        }
-                        else
-                        {
-                            throw;
-                        }
-                    }
-                    catch (TargetInvocationException targetInvocationException)
-                    {
-                        if (targetInvocationException.InnerException == null)
-                            throw;
-                        //We are catching the TIE here and throws the inner exception only,
-                        //this is needed to have a consistent exception story in all serializers
-                        throw targetInvocationException.InnerException;
-                    }
-                }
-            }
-        }
-
-        internal static void InvokeOnDeserializing(object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context)
-        {
-            if (contract is ClassDataContract classContract)
-            {
-                if (classContract.BaseContract != null)
-                    InvokeOnDeserializing(value, classContract.BaseContract, context);
-                if (classContract.OnDeserializing != null)
-                {
-                    bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null);
-                    try
-                    {
-                        classContract.OnDeserializing.Invoke(value, new object[] { context.GetStreamingContext() });
-                    }
-                    catch (SecurityException securityException)
-                    {
-                        if (memberAccessFlag)
-                        {
-                            classContract.RequiresMemberAccessForRead(securityException);
-                        }
-                        else
-                        {
-                            throw;
-                        }
-                    }
-                    catch (TargetInvocationException targetInvocationException)
-                    {
-                        if (targetInvocationException.InnerException == null)
-                            throw;
-                        //We are catching the TIE here and throws the inner exception only,
-                        //this is needed to have a consistent exception story in all serializers
-                        throw targetInvocationException.InnerException;
-                    }
-                }
-            }
-        }
-
-        internal static void InvokeOnDeserialized(object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context)
-        {
-            if (contract is ClassDataContract classContract)
-            {
-                if (classContract.BaseContract != null)
-                    InvokeOnDeserialized(value, classContract.BaseContract, context);
-                if (classContract.OnDeserialized != null)
-                {
-                    bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null);
-                    try
-                    {
-                        classContract.OnDeserialized.Invoke(value, new object[] { context.GetStreamingContext() });
-                    }
-                    catch (SecurityException securityException)
-                    {
-                        if (memberAccessFlag)
-                        {
-                            classContract.RequiresMemberAccessForRead(securityException);
-                        }
-                        else
-                        {
-                            throw;
-                        }
-                    }
-                    catch (TargetInvocationException targetInvocationException)
-                    {
-                        if (targetInvocationException.InnerException == null)
-                            throw;
-                        //We are catching the TIE here and throws the inner exception only,
-                        //this is needed to have a consistent exception story in all serializers
-                        throw targetInvocationException.InnerException;
-                    }
-                }
-            }
-        }
-
-        internal static bool CharacterNeedsEscaping(char ch)
-        {
-            return (ch == FORWARD_SLASH || ch == JsonGlobals.QuoteChar || ch < WHITESPACE || ch == BACK_SLASH
-                || (ch >= HIGH_SURROGATE_START && (ch <= LOW_SURROGATE_END || ch >= MAX_CHAR)));
-        }
-
-        internal static bool CheckIfJsonNameRequiresMapping(string jsonName)
-        {
-            if (jsonName != null)
+            if (settings == null)
             {
-                if (!DataContract.IsValidNCName(jsonName))
-                {
-                    return true;
-                }
-
-                for (int i = 0; i < jsonName.Length; i++)
-                {
-                    if (CharacterNeedsEscaping(jsonName[i]))
-                    {
-                        return true;
-                    }
-                }
+                settings = new DataContractJsonSerializerSettings();
             }
-            return false;
-        }
-
-        internal static bool CheckIfJsonNameRequiresMapping(XmlDictionaryString jsonName)
-        {
-            return (jsonName == null) ? false : CheckIfJsonNameRequiresMapping(jsonName.Value);
-        }
 
-        internal static string ConvertXmlNameToJsonName(string xmlName)
-        {
-            return XmlConvert.DecodeName(xmlName);
-        }
-
-        internal static XmlDictionaryString? ConvertXmlNameToJsonName(XmlDictionaryString? xmlName)
-        {
-            return (xmlName == null) ? null : new XmlDictionary().Add(ConvertXmlNameToJsonName(xmlName.Value));
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        internal static object? ReadJsonValue(DataContract contract, XmlReaderDelegator reader, XmlObjectSerializerReadContextComplexJson context)
-        {
-            return JsonDataContract.GetJsonDataContract(contract).ReadJsonValue(reader, context);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        internal static void WriteJsonValue(JsonDataContract contract, XmlWriterDelegator writer, object graph, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
-        {
-            contract.WriteJsonValue(writer, graph, context, declaredTypeHandle);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteStartObject(XmlWriter writer, object? graph)
-        {
-            _serializer.WriteStartObject(writer, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteStartObject(XmlDictionaryWriter writer, object? graph)
-        {
-            _serializer.WriteStartObject(writer, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteObjectContent(XmlWriter writer, object? graph)
-        {
-            _serializer.WriteObjectContent(writer, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteObjectContent(XmlDictionaryWriter writer, object? graph)
-        {
-            _serializer.WriteObjectContent(writer, graph);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteEndObject(XmlWriter writer)
-        {
-            _serializer.WriteEndObject(writer);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override void WriteEndObject(XmlDictionaryWriter writer)
-        {
-            _serializer.WriteEndObject(writer);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override object? ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
-        {
-            return _serializer.ReadObject(reader, verifyObjectName);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override bool IsStartObject(XmlReader reader)
-        {
-            return _serializer.IsStartObject(reader);
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public override bool IsStartObject(XmlDictionaryReader reader)
-        {
-            return _serializer.IsStartObject(reader);
-        }
-    }
-
-    internal sealed class DataContractJsonSerializerImpl : XmlObjectSerializer
-    {
-        internal IList<Type>? knownTypeList;
-        internal DataContractDictionary? knownDataContracts;
-        private EmitTypeInformation _emitTypeInformation;
-        private bool _ignoreExtensionDataObject;
-        private ReadOnlyCollection<Type>? _knownTypeCollection;
-        private int _maxItemsInObjectGraph;
-        private DataContract? _rootContract; // post-surrogate
-        private XmlDictionaryString? _rootName;
-        private bool _rootNameRequiresMapping;
-        private Type _rootType;
-        private bool _serializeReadOnlyTypes;
-        private DateTimeFormat? _dateTimeFormat;
-        private bool _useSimpleDictionaryFormat;
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public DataContractJsonSerializerImpl(Type type)
-            : this(type, (IEnumerable<Type>?)null)
-        {
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public DataContractJsonSerializerImpl(Type type, IEnumerable<Type>? knownTypes)
-            : this(type, null, knownTypes, int.MaxValue, false, false)
-        {
-        }
-
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public DataContractJsonSerializerImpl(Type type, XmlDictionaryString? rootName, IEnumerable<Type>? knownTypes)
-            : this(type, rootName, knownTypes, int.MaxValue, false, false)
-        {
+            XmlDictionaryString? rootName = (settings.RootName == null) ? null : new XmlDictionary(1).Add(settings.RootName);
+            Initialize(type, rootName, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject,
+                settings.EmitTypeInformation, settings.SerializeReadOnlyTypes, settings.DateTimeFormat, settings.UseSimpleDictionaryFormat);
         }
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        internal DataContractJsonSerializerImpl(Type type,
+        internal DataContractJsonSerializer(Type type,
             XmlDictionaryString? rootName,
             IEnumerable<Type>? knownTypes,
             int maxItemsInObjectGraph,
@@ -554,17 +96,9 @@ namespace System.Runtime.Serialization.Json
             Initialize(type, rootName, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, emitTypeInformation, false, null, false);
         }
 
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        public DataContractJsonSerializerImpl(Type type, DataContractJsonSerializerSettings? settings)
+        public bool IgnoreExtensionDataObject
         {
-            if (settings == null)
-            {
-                settings = new DataContractJsonSerializerSettings();
-            }
-
-            XmlDictionaryString? rootName = (settings.RootName == null) ? null : new XmlDictionary(1).Add(settings.RootName);
-            Initialize(type, rootName, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject,
-                settings.EmitTypeInformation, settings.SerializeReadOnlyTypes, settings.DateTimeFormat, settings.UseSimpleDictionaryFormat);
+            get { return _ignoreExtensionDataObject; }
         }
 
         public ReadOnlyCollection<Type> KnownTypes
@@ -603,16 +137,16 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        internal int MaxItemsInObjectGraph
+        public int MaxItemsInObjectGraph
         {
             get { return _maxItemsInObjectGraph; }
         }
 
-        internal bool AlwaysEmitTypeInformation
+        public DateTimeFormat? DateTimeFormat
         {
             get
             {
-                return _emitTypeInformation == EmitTypeInformation.Always;
+                return _dateTimeFormat;
             }
         }
 
@@ -632,13 +166,6 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        public DateTimeFormat? DateTimeFormat
-        {
-            get
-            {
-                return _dateTimeFormat;
-            }
-        }
 
         public bool UseSimpleDictionaryFormat
         {
@@ -893,7 +420,7 @@ namespace System.Runtime.Serialization.Json
             DataContract contract = RootContract;
             if (contract.IsPrimitive && object.ReferenceEquals(contract.UnderlyingType, _rootType))// handle Nullable<T> differently
             {
-                return DataContractJsonSerializerImpl.ReadJsonValue(contract, xmlReader, null);
+                return DataContractJsonSerializer.ReadJsonValue(contract, xmlReader, null);
             }
 
             XmlObjectSerializerReadContextComplexJson context = XmlObjectSerializerReadContextComplexJson.CreateContext(this, contract);
@@ -926,11 +453,6 @@ namespace System.Runtime.Serialization.Json
             Type declaredType = contract.UnderlyingType;
             Type graphType = (graph == null) ? declaredType : graph.GetType();
 
-            //if (dataContractSurrogate != null)
-            //{
-            //    graph = DataContractSerializer.SurrogateToDataContractType(dataContractSurrogate, graph, declaredType, ref graphType);
-            //}
-
             if (graph == null)
             {
                 WriteJsonNull(writer);
@@ -947,13 +469,13 @@ namespace System.Runtime.Serialization.Json
                     }
                     else
                     {
-                        DataContractJsonSerializerImpl.WriteJsonValue(JsonDataContract.GetJsonDataContract(contract), writer, graph, null, declaredType.TypeHandle); //  XmlObjectSerializerWriteContextComplexJson
+                        DataContractJsonSerializer.WriteJsonValue(JsonDataContract.GetJsonDataContract(contract), writer, graph, null, declaredType.TypeHandle); //  XmlObjectSerializerWriteContextComplexJson
                     }
                 }
                 else
                 {
                     XmlObjectSerializerWriteContextComplexJson context = XmlObjectSerializerWriteContextComplexJson.CreateContext(this, RootContract);
-                    contract = DataContractJsonSerializerImpl.GetDataContract(contract, declaredType, graphType);
+                    contract = DataContractJsonSerializer.GetDataContract(contract, declaredType, graphType);
                     if (contract.CanContainReferences)
                     {
                         context.OnHandleReference(writer, graph, true); //  canContainCyclicReference
@@ -1057,7 +579,11 @@ namespace System.Runtime.Serialization.Json
         {
             if (dataContract.IsReference)
             {
-                throw XmlObjectSerializer.CreateSerializationException(SR.Format(SR.JsonUnsupportedForIsReference, DataContract.GetClrTypeFullName(dataContract.UnderlyingType), dataContract.IsReference));
+                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
+                    XmlObjectSerializer.CreateSerializationException(SR.Format(
+                        SR.JsonUnsupportedForIsReference,
+                        DataContract.GetClrTypeFullName(dataContract.UnderlyingType),
+                        dataContract.IsReference)));
             }
         }
 
index 148b3ee..6ff59d9 100644 (file)
@@ -21,12 +21,6 @@ namespace System.Runtime.Serialization.Json
             _helper = (base.Helper as JsonClassDataContractCriticalHelper)!;
         }
 
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        private JsonFormatClassReaderDelegate CreateJsonFormatReaderDelegate()
-        {
-            return new ReflectionJsonClassReader(TraditionalClassDataContract).ReflectionReadClass;
-        }
-
         internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate
         {
             [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -41,7 +35,7 @@ namespace System.Runtime.Serialization.Json
                             JsonFormatClassReaderDelegate tempDelegate;
                             if (DataContractSerializer.Option == SerializationOption.ReflectionOnly)
                             {
-                                tempDelegate = CreateJsonFormatReaderDelegate();
+                                tempDelegate = new ReflectionJsonClassReader(TraditionalClassDataContract).ReflectionReadClass;
                             }
                             else
                             {
@@ -57,12 +51,6 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        private JsonFormatClassWriterDelegate CreateJsonFormatWriterDelegate()
-        {
-            return new ReflectionJsonFormatWriter().ReflectionWriteClass;
-        }
-
         internal JsonFormatClassWriterDelegate JsonFormatWriterDelegate
         {
             [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -77,7 +65,7 @@ namespace System.Runtime.Serialization.Json
                             JsonFormatClassWriterDelegate tempDelegate;
                             if (DataContractSerializer.Option == SerializationOption.ReflectionOnly)
                             {
-                                tempDelegate = CreateJsonFormatWriterDelegate();
+                                tempDelegate = new ReflectionJsonFormatWriter().ReflectionWriteClass;
                             }
                             else
                             {
@@ -171,7 +159,7 @@ namespace System.Runtime.Serialization.Json
                         else
                         {
                             memberTable.Add(_traditionalClassDataContract.MemberNames[i].Value, null);
-                            decodedMemberNames[i] = DataContractJsonSerializerImpl.ConvertXmlNameToJsonName(_traditionalClassDataContract.MemberNames[i]);
+                            decodedMemberNames[i] = DataContractJsonSerializer.ConvertXmlNameToJsonName(_traditionalClassDataContract.MemberNames[i]);
                         }
                     }
                     _memberNames = decodedMemberNames;
index 8fe2e96..0ed183e 100644 (file)
@@ -21,12 +21,6 @@ namespace System.Runtime.Serialization.Json
             _helper = (base.Helper as JsonCollectionDataContractCriticalHelper)!;
         }
 
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        private JsonFormatCollectionReaderDelegate CreateJsonFormatReaderDelegate()
-        {
-            return new ReflectionJsonCollectionReader().ReflectionReadCollection;
-        }
-
         internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate
         {
             [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -41,7 +35,7 @@ namespace System.Runtime.Serialization.Json
                             JsonFormatCollectionReaderDelegate tempDelegate;
                             if (DataContractSerializer.Option == SerializationOption.ReflectionOnly)
                             {
-                                tempDelegate = CreateJsonFormatReaderDelegate();
+                                tempDelegate = new ReflectionJsonCollectionReader().ReflectionReadCollection;
                             }
                             else
                             {
@@ -57,12 +51,6 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        private JsonFormatGetOnlyCollectionReaderDelegate CreateJsonFormatGetOnlyReaderDelegate()
-        {
-            return new ReflectionJsonCollectionReader().ReflectionReadGetOnlyCollection;
-        }
-
         internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate
         {
             [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -83,7 +71,7 @@ namespace System.Runtime.Serialization.Json
                             JsonFormatGetOnlyCollectionReaderDelegate tempDelegate;
                             if (DataContractSerializer.Option == SerializationOption.ReflectionOnly)
                             {
-                                tempDelegate = CreateJsonFormatGetOnlyReaderDelegate();
+                                tempDelegate = new ReflectionJsonCollectionReader().ReflectionReadGetOnlyCollection;
                             }
                             else
                             {
@@ -99,13 +87,6 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
-        private JsonFormatCollectionWriterDelegate CreateJsonFormatWriterDelegate()
-        {
-            return new ReflectionJsonFormatWriter().ReflectionWriteCollection;
-        }
-
-
         internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate
         {
             [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -120,7 +101,7 @@ namespace System.Runtime.Serialization.Json
                             JsonFormatCollectionWriterDelegate tempDelegate;
                             if (DataContractSerializer.Option == SerializationOption.ReflectionOnly)
                             {
-                                tempDelegate = CreateJsonFormatWriterDelegate();
+                                tempDelegate = new ReflectionJsonFormatWriter().ReflectionWriteCollection;
                             }
                             else
                             {
index fa2b5ae..44b0bda 100644 (file)
@@ -439,8 +439,7 @@ namespace System.Runtime.Serialization.Json
         {
             try
             {
-                //this.stream = new BufferedStream(inputStream);
-                _stream = inputStream;
+                _stream = new BufferedStream(inputStream);
 
                 SupportedEncoding expectedEnc = GetSupportedEncoding(expectedEncoding);
                 SupportedEncoding dataEnc = ReadEncoding();
@@ -472,8 +471,7 @@ namespace System.Runtime.Serialization.Json
         private void InitForWriting(Stream outputStream, Encoding writeEncoding)
         {
             _encoding = writeEncoding;
-            //this.stream = new BufferedStream(outputStream);
-            _stream = outputStream;
+            _stream = new BufferedStream(outputStream);
 
             // Set the encoding code
             _encodingCode = GetSupportedEncoding(writeEncoding);
index d7f05cd..fa3a0fe 100644 (file)
@@ -13,6 +13,8 @@ namespace System.Runtime.Serialization
 {
     public static class JsonFormatGeneratorStatics
     {
+        private static MethodInfo? s_boxPointer;
+
         private static PropertyInfo? s_collectionItemNameProperty;
 
         private static ConstructorInfo? s_extensionDataObjectCtor;
@@ -59,6 +61,8 @@ namespace System.Runtime.Serialization
 
         private static PropertyInfo? s_typeHandleProperty;
 
+        private static MethodInfo? s_unboxPointer;
+
         private static PropertyInfo? s_useSimpleDictionaryFormatReadProperty;
 
         private static PropertyInfo? s_useSimpleDictionaryFormatWriteProperty;
@@ -81,6 +85,19 @@ namespace System.Runtime.Serialization
 
         private static MethodInfo? s_getJsonMemberNameMethod;
 
+        public static MethodInfo BoxPointer
+        {
+            get
+            {
+                if (s_boxPointer == null)
+                {
+                    s_boxPointer = typeof(Pointer).GetMethod("Box");
+                    Debug.Assert(s_boxPointer != null);
+                }
+                return s_boxPointer;
+            }
+        }
+
         public static PropertyInfo CollectionItemNameProperty
         {
             get
@@ -349,6 +366,18 @@ namespace System.Runtime.Serialization
                 return s_typeHandleProperty;
             }
         }
+        public static MethodInfo UnboxPointer
+        {
+            get
+            {
+                if (s_unboxPointer == null)
+                {
+                    s_unboxPointer = typeof(Pointer).GetMethod("Unbox");
+                    Debug.Assert(s_unboxPointer != null);
+                }
+                return s_unboxPointer;
+            }
+        }
         public static PropertyInfo UseSimpleDictionaryFormatReadProperty
         {
             get
index 9f2bad8..13be224 100644 (file)
@@ -563,7 +563,14 @@ namespace System.Runtime.Serialization.Json
                 _ilg.Load(string.Empty);
                 _ilg.Call(XmlFormatGeneratorStatics.InternalDeserializeMethod);
 
-                _ilg.ConvertValue(Globals.TypeOfObject, type);
+                if (type.IsPointer)
+                {
+                    _ilg.Call(JsonFormatGeneratorStatics.UnboxPointer);
+                }
+                else
+                {
+                    _ilg.ConvertValue(Globals.TypeOfObject, type);
+                }
                 _ilg.Stloc(value);
             }
 
index a76f918..94089b7 100644 (file)
@@ -107,6 +107,10 @@ namespace System.Runtime.Serialization.Json
                     }
                 }
                 InitArgs(collectionContract.UnderlyingType);
+                if (collectionContract.IsReadOnlyContract)
+                {
+                    ThrowIfCannotSerializeReadOnlyTypes(collectionContract);
+                }
                 WriteCollection(collectionContract);
                 return (JsonFormatCollectionWriterDelegate)_ilg.EndMethod();
             }
@@ -162,6 +166,23 @@ namespace System.Runtime.Serialization.Json
                 _ilg.Stloc(_objectLocal);
             }
 
+            private void ThrowIfCannotSerializeReadOnlyTypes(CollectionDataContract classContract)
+            {
+                ThrowIfCannotSerializeReadOnlyTypes(XmlFormatGeneratorStatics.CollectionSerializationExceptionMessageProperty);
+            }
+
+            private void ThrowIfCannotSerializeReadOnlyTypes(PropertyInfo serializationExceptionMessageProperty)
+            {
+                _ilg.Load(_contextArg);
+                _ilg.LoadMember(XmlFormatGeneratorStatics.SerializeReadOnlyTypesProperty);
+                _ilg.IfNot();
+                _ilg.Load(_dataContractArg);
+                _ilg.LoadMember(serializationExceptionMessageProperty);
+                _ilg.Load(null);
+                _ilg.Call(XmlFormatGeneratorStatics.ThrowInvalidDataContractExceptionMethod);
+                _ilg.EndIf();
+            }
+
             private void InvokeOnSerializing(ClassDataContract classContract)
             {
                 if (classContract.BaseContract != null)
@@ -243,7 +264,7 @@ namespace System.Runtime.Serialization.Json
                         _ilg.IfNotDefaultValue(memberValue);
                     }
 
-                    bool requiresNameAttribute = DataContractJsonSerializerImpl.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]);
+                    bool requiresNameAttribute = DataContractJsonSerializer.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]);
                     if (requiresNameAttribute || !TryWritePrimitive(memberType, memberValue, member.MemberInfo, arrayItemIndex: null, name: null, nameIndex: i + _childElementIndex))
                     {
                         // Note: DataContractSerializer has member-conflict logic here to deal with the schema export
@@ -554,7 +575,7 @@ namespace System.Runtime.Serialization.Json
                     return false;
 
                 string? writeArrayMethod = null;
-                switch (itemType.GetTypeCode())
+                switch (Type.GetTypeCode(itemType))
                 {
                     case TypeCode.Boolean:
                         writeArrayMethod = "WriteJsonBooleanArray";
@@ -616,6 +637,15 @@ namespace System.Runtime.Serialization.Json
             private void WriteValue(LocalBuilder memberValue)
             {
                 Type memberType = memberValue.LocalType;
+                if (memberType.IsPointer)
+                {
+                    _ilg.Load(memberValue);
+                    _ilg.Load(memberType);
+                    _ilg.Call(JsonFormatGeneratorStatics.BoxPointer);
+                    memberType = typeof(System.Reflection.Pointer);
+                    memberValue = _ilg.DeclareLocal(memberType, "memberValueRefPointer");
+                    _ilg.Store(memberValue);
+                }
                 bool isNullableOfT = (memberType.IsGenericType &&
                                       memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable);
                 if (memberType.IsValueType && !isNullableOfT)
@@ -739,7 +769,7 @@ namespace System.Runtime.Serialization.Json
                 // namespace
                 _ilg.Load(null);
 
-                if (nameLocal != null && nameLocal.LocalType == Globals.TypeOfString)
+                if (nameLocal != null && nameLocal.LocalType == typeof(string))
                 {
                     _ilg.Call(JsonFormatGeneratorStatics.WriteStartElementStringMethod);
                 }
index 40e3420..d7e72a1 100644 (file)
@@ -44,7 +44,7 @@ namespace System.Runtime.Serialization.Json
                     break;
                 case JsonGlobals.arrayString:
                     // Read as object array
-                    return DataContractJsonSerializerImpl.ReadJsonValue(DataContract.GetDataContract(Globals.TypeOfObjectArray), jsonReader, context);
+                    return DataContractJsonSerializer.ReadJsonValue(DataContract.GetDataContract(Globals.TypeOfObjectArray), jsonReader, context);
                 default:
                     throw XmlObjectSerializer.CreateSerializationException(SR.Format(SR.JsonUnexpectedAttributeValue, contentMode));
             }
index 10aff10..aea41cb 100644 (file)
@@ -243,7 +243,7 @@ namespace System.Runtime.Serialization.Json
                     {
                         memberValue = ReflectionGetMemberValue(obj, member);
                     }
-                    bool requiresNameAttribute = DataContractJsonSerializerImpl.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]);
+                    bool requiresNameAttribute = DataContractJsonSerializer.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]);
                     PrimitiveDataContract? primitiveContract = member.MemberPrimitiveContract;
                     if (requiresNameAttribute || !ReflectionTryWritePrimitive(xmlWriter, context, memberType, memberValue, memberNames[i + childElementIndex] /*name*/, null/*ns*/, primitiveContract))
                     {
index 21c6548..a4faf48 100644 (file)
@@ -337,7 +337,7 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        protected override void Dispose(bool disposing)
+        public override void Close()
         {
             OnXmlDictionaryReaderClose? onClose = _onReaderClose;
             _onReaderClose = null;
@@ -353,7 +353,8 @@ namespace System.Runtime.Serialization.Json
                     throw new InvalidOperationException(SR.GenericCallbackException, e);
                 }
             }
-            base.Dispose(disposing);
+
+            base.Close();
         }
 
         public override void EndCanonicalization()
index d52d1fa..8ce76f7 100644 (file)
@@ -193,7 +193,7 @@ namespace System.Runtime.Serialization.Json
 
         private bool WrittenNameWithMapping => (_nameState & NameState.WrittenNameWithMapping) == NameState.WrittenNameWithMapping;
 
-        protected override void Dispose(bool disposing)
+        public override void Close()
         {
             if (!IsClosed)
             {
@@ -219,7 +219,7 @@ namespace System.Runtime.Serialization.Json
                 }
             }
 
-            base.Dispose(disposing);
+            base.Close();
         }
 
         public override void Flush()
@@ -262,21 +262,20 @@ namespace System.Runtime.Serialization.Json
             {
                 throw new ArgumentNullException(nameof(encoding));
             }
-            Encoding? tempEncoding = encoding;
-            if (tempEncoding.WebName != Encoding.UTF8.WebName)
+            if (encoding.WebName != Encoding.UTF8.WebName)
             {
-                stream = new JsonEncodingStreamWrapper(stream, tempEncoding, false);
+                stream = new JsonEncodingStreamWrapper(stream, encoding, false);
             }
             else
             {
-                tempEncoding = null;
+                encoding = null!;
             }
             if (_nodeWriter == null)
             {
                 _nodeWriter = new JsonNodeWriter();
             }
 
-            _nodeWriter.SetOutput(stream, ownsStream, tempEncoding);
+            _nodeWriter.SetOutput(stream, ownsStream, encoding);
             InitializeWriter();
         }
 
index d571c73..a43cb27 100644 (file)
@@ -7,8 +7,6 @@ using System.Text;
 using System.Reflection;
 using System.Xml;
 using System.Runtime.Serialization;
-using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, System.Runtime.Serialization.DataContract>;
-using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.Serialization.Json
@@ -19,8 +17,8 @@ namespace System.Runtime.Serialization.Json
         private readonly DateTimeFormat? _dateTimeFormat;
         private readonly bool _useSimpleDictionaryFormat;
 
-        internal XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract)
-            : base(serializer, serializer.MaxItemsInObjectGraph, default(StreamingContext), false)
+        internal XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
+            : base(serializer, serializer.MaxItemsInObjectGraph, new StreamingContext(StreamingContextStates.All), serializer.IgnoreExtensionDataObject)
         {
             this.rootTypeDataContract = rootTypeDataContract;
             this.serializerKnownTypeList = serializer.knownTypeList;
@@ -28,7 +26,7 @@ namespace System.Runtime.Serialization.Json
             _useSimpleDictionaryFormat = serializer.UseSimpleDictionaryFormat;
         }
 
-        internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract)
+        internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
         {
             return new XmlObjectSerializerReadContextComplexJson(serializer, rootTypeDataContract);
         }
@@ -36,7 +34,7 @@ namespace System.Runtime.Serialization.Json
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         protected override object? ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
         {
-            return DataContractJsonSerializerImpl.ReadJsonValue(dataContract, reader, this);
+            return DataContractJsonSerializer.ReadJsonValue(dataContract, reader, this);
         }
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -135,6 +133,11 @@ namespace System.Runtime.Serialization.Json
             };
         }
 
+        internal override int GetArraySize()
+        {
+            return -1;
+        }
+
         internal override void ReadAttributes(XmlReaderDelegator xmlReader)
         {
             if (attributes == null)
@@ -238,6 +241,21 @@ namespace System.Runtime.Serialization.Json
             return new XmlQualifiedName(name, ns);
         }
 
+        protected override bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader)
+        {
+            return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.arrayString;
+        }
+
+        protected override bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader)
+        {
+            return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.objectString;
+        }
+
+        protected override XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader)
+        {
+            return new JsonReaderDelegator(xmlReader, this._dateTimeFormat);
+        }
+
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type? type)
         {
@@ -323,5 +341,11 @@ namespace System.Runtime.Serialization.Json
         {
             return BitFlagsGenerator.IsBitSet(bytes, bitIndex);
         }
+
+        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+        protected override DataContract? ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
+        {
+            return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract!);
+        }
     }
 }
index 6519fba..f107c5b 100644 (file)
@@ -8,7 +8,6 @@ using System.Xml;
 using System.Reflection;
 using System.Collections;
 using System.IO;
-using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, System.Runtime.Serialization.DataContract>;
 using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.Serialization.Json
@@ -19,13 +18,13 @@ namespace System.Runtime.Serialization.Json
         private bool _perCallXsiTypeAlreadyEmitted;
         private readonly bool _useSimpleDictionaryFormat;
 
-        internal static XmlObjectSerializerWriteContextComplexJson CreateContext(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract)
+        internal static XmlObjectSerializerWriteContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
         {
             return new XmlObjectSerializerWriteContextComplexJson(serializer, rootTypeDataContract);
         }
 
-        internal XmlObjectSerializerWriteContextComplexJson(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract)
-            : base(serializer, serializer.MaxItemsInObjectGraph, default(StreamingContext), false)
+        internal XmlObjectSerializerWriteContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
+            : base(serializer, serializer.MaxItemsInObjectGraph, new StreamingContext(StreamingContextStates.All), serializer.IgnoreExtensionDataObject)
         {
             _emitXsiType = serializer.EmitTypeInformation;
             this.rootTypeDataContract = rootTypeDataContract;
@@ -50,16 +49,6 @@ namespace System.Runtime.Serialization.Json
             }
         }
 
-        internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, string clrTypeName, string clrAssemblyName)
-        {
-            return false;
-        }
-
-        internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, DataContract dataContract)
-        {
-            return false;
-        }
-
         internal override void WriteArraySize(XmlWriterDelegator xmlWriter, int size)
         {
             //Noop
@@ -161,12 +150,12 @@ namespace System.Runtime.Serialization.Json
                 WriteTypeInfo(xmlWriter, jsonDataContract.TypeName!);
             }
             _perCallXsiTypeAlreadyEmitted = false;
-            DataContractJsonSerializerImpl.WriteJsonValue(jsonDataContract, xmlWriter, obj, this, declaredTypeHandle);
+            DataContractJsonSerializer.WriteJsonValue(jsonDataContract, xmlWriter, obj, this, declaredTypeHandle);
         }
 
         protected override void WriteNull(XmlWriterDelegator xmlWriter)
         {
-            DataContractJsonSerializerImpl.WriteJsonNull(xmlWriter);
+            DataContractJsonSerializer.WriteJsonNull(xmlWriter);
         }
 
         internal XmlDictionaryString CollectionItemName
@@ -384,5 +373,39 @@ namespace System.Runtime.Serialization.Json
             DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
             return dataContract;
         }
+
+        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+        protected override DataContract? ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
+        {
+            return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract!);
+        }
+
+        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+        internal static DataContract? ResolveJsonDataContractFromRootDataContract(XmlObjectSerializerContext context, XmlQualifiedName typeQName, DataContract rootTypeDataContract)
+        {
+            if (rootTypeDataContract.StableName == typeQName)
+                return rootTypeDataContract;
+
+            CollectionDataContract? collectionContract = rootTypeDataContract as CollectionDataContract;
+            while (collectionContract != null)
+            {
+                DataContract itemContract;
+                if (collectionContract.ItemType.IsGenericType
+                    && collectionContract.ItemType.GetGenericTypeDefinition() == typeof(KeyValue<,>))
+                {
+                    itemContract = context.GetDataContract(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments()));
+                }
+                else
+                {
+                    itemContract = context.GetDataContract(context.GetSurrogatedType(collectionContract.ItemType));
+                }
+                if (itemContract.StableName == typeQName)
+                {
+                    return itemContract;
+                }
+                collectionContract = itemContract as CollectionDataContract;
+            }
+            return null;
+        }
     }
 }
index 9323ae8..4ef2743 100644 (file)
@@ -281,25 +281,29 @@ namespace System.Runtime.Serialization
                     if (rootTypeDataContract.StableName == qname)
                         dataContract = rootTypeDataContract;
                     else
-                    {
-                        CollectionDataContract? collectionContract = rootTypeDataContract as CollectionDataContract;
-                        while (collectionContract != null)
-                        {
-                            DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType));
-                            if (itemContract.StableName == qname)
-                            {
-                                dataContract = itemContract;
-                                break;
-                            }
-                            collectionContract = itemContract as CollectionDataContract;
-                        }
-                    }
+                        dataContract = ResolveDataContractFromRootDataContract(qname);
                 }
             }
             return dataContract;
         }
 
         [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+        protected virtual DataContract? ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
+        {
+            CollectionDataContract? collectionContract = rootTypeDataContract as CollectionDataContract;
+            while (collectionContract != null)
+            {
+                DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType));
+                if (itemContract.StableName == typeQName)
+                {
+                    return itemContract;
+                }
+                collectionContract = itemContract as CollectionDataContract;
+            }
+            return null;
+        }
+
+        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
         internal void PushKnownTypes(DataContract dc)
         {
             if (dc != null && dc.KnownDataContracts != null)
index 87cd308..b8d386a 100644 (file)
@@ -2384,6 +2384,38 @@ public static partial class DataContractJsonSerializerTests
         }
     }
 
+    [Fact]
+    public static void DCJS_ExtensionDataObjectTest2()
+    {
+        SerializeThenDeserialize(new ContractExtended { Item = new Item { Id = 1, Code = 2 } });
+        SerializeThenDeserialize(new ContractExtended { Item = new Item { Id = 1 } });
+    }
+
+    private static void SerializeThenDeserialize(ContractExtended extendedData)
+    {
+        string extendedContractJson;
+        using (var memoryStream = new MemoryStream())
+        {
+            new DataContractJsonSerializer(typeof(ContractExtended)).WriteObject(memoryStream, extendedData);
+            extendedContractJson = Encoding.UTF8.GetString(memoryStream.ToArray());
+        }
+
+        ContractGeneric reducedData;
+        using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(extendedContractJson)))
+        {
+            reducedData = (ContractGeneric)new DataContractJsonSerializer(typeof(ContractGeneric)).ReadObject(memoryStream);
+        }
+
+        string reducedContractJson;
+        using (var memoryStream = new MemoryStream())
+        {
+            new DataContractJsonSerializer(typeof(ContractGeneric)).WriteObject(memoryStream, reducedData);
+            reducedContractJson = Encoding.UTF8.GetString(memoryStream.ToArray());
+        }
+
+        Assert.Equal(extendedContractJson, reducedContractJson);
+    }
+
     private static string ConstructorWithRootNameTestHelper(TypeForRootNameTest value, DataContractJsonSerializer serializer)
     {
         using (var ms = new MemoryStream())
index 95d51d4..abe72c6 100644 (file)
@@ -4347,6 +4347,29 @@ public class NativeJsonTestData
     public Func<object> Instantiate { get; set; }
 }
 
+[DataContract]
+public class ContractGeneric : IExtensibleDataObject
+{
+    public ExtensionDataObject ExtensionData { get; set; }
+}
+
+[DataContract(Name = "ContractGeneric")]
+public class ContractExtended
+{
+    [DataMember(Name = "item", Order = 1)]
+    public Item Item;
+}
+
+[DataContract]
+public class Item
+{
+    [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)]
+    public long? Id;
+
+    [DataMember(Name = "code", Order = 2, EmitDefaultValue = false)]
+    public long? Code;
+}
+
 public class TypeWithCollectionAndDateTimeOffset
 {
     public TypeWithCollectionAndDateTimeOffset()