| File: System\Runtime\Serialization\Json\JsonClassDataContract.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.DataContractSerialization\src\System.Private.DataContractSerialization.csproj (System.Private.DataContractSerialization) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.Serialization.DataContracts; using System.Threading; using System.Xml; namespace System.Runtime.Serialization.Json { internal sealed class JsonClassDataContract : JsonDataContract { private readonly JsonClassDataContractCriticalHelper _helper; [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public JsonClassDataContract(ClassDataContract traditionalDataContract) : base(new JsonClassDataContractCriticalHelper(traditionalDataContract)) { _helper = (base.Helper as JsonClassDataContractCriticalHelper)!; } internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate { [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] get { if (_helper.JsonFormatReaderDelegate == null) { lock (this) { if (_helper.JsonFormatReaderDelegate == null) { JsonFormatClassReaderDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { tempDelegate = new ReflectionJsonClassReader(TraditionalClassDataContract).ReflectionReadClass; } else { tempDelegate = new JsonFormatReaderGenerator().GenerateClassReader(TraditionalClassDataContract); } Interlocked.MemoryBarrier(); _helper.JsonFormatReaderDelegate = tempDelegate; } } } return _helper.JsonFormatReaderDelegate; } } internal JsonFormatClassWriterDelegate JsonFormatWriterDelegate { [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] get { if (_helper.JsonFormatWriterDelegate == null) { lock (this) { if (_helper.JsonFormatWriterDelegate == null) { JsonFormatClassWriterDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { tempDelegate = new ReflectionJsonFormatWriter().ReflectionWriteClass; } else { tempDelegate = new JsonFormatWriterGenerator().GenerateClassWriter(TraditionalClassDataContract); } Interlocked.MemoryBarrier(); _helper.JsonFormatWriterDelegate = tempDelegate; } } } return _helper.JsonFormatWriterDelegate; } } internal XmlDictionaryString[]? MemberNames => _helper.MemberNames; internal override string TypeName => _helper.TypeName; private ClassDataContract TraditionalClassDataContract => _helper.TraditionalClassDataContract; [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public override object? ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson? context) { jsonReader.Read(); object o = JsonFormatReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, MemberNames); jsonReader.ReadEndElement(); return o; } [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public override void WriteJsonValueCore(XmlWriterDelegator jsonWriter, object obj, XmlObjectSerializerWriteContextComplexJson? context, RuntimeTypeHandle declaredTypeHandle) { Debug.Assert(context != null); jsonWriter.WriteAttributeString(null, JsonGlobals.typeString, null, JsonGlobals.objectString); JsonFormatWriterDelegate(jsonWriter, obj, context, TraditionalClassDataContract, MemberNames); } private sealed class JsonClassDataContractCriticalHelper : JsonDataContractCriticalHelper { private JsonFormatClassReaderDelegate? _jsonFormatReaderDelegate; private JsonFormatClassWriterDelegate? _jsonFormatWriterDelegate; private XmlDictionaryString[]? _memberNames; private readonly ClassDataContract _traditionalClassDataContract; private readonly string _typeName; [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public JsonClassDataContractCriticalHelper(ClassDataContract traditionalDataContract) : base(traditionalDataContract) { _typeName = string.IsNullOrEmpty(traditionalDataContract.Namespace.Value) ? traditionalDataContract.Name.Value : string.Concat(traditionalDataContract.Name.Value, JsonGlobals.NameValueSeparatorString, XmlObjectSerializerWriteContextComplexJson.TruncateDefaultDataContractNamespace(traditionalDataContract.Namespace.Value)); _traditionalClassDataContract = traditionalDataContract; CopyMembersAndCheckDuplicateNames(); } internal JsonFormatClassReaderDelegate? JsonFormatReaderDelegate { get { return _jsonFormatReaderDelegate; } set { _jsonFormatReaderDelegate = value; } } internal JsonFormatClassWriterDelegate? JsonFormatWriterDelegate { get { return _jsonFormatWriterDelegate; } set { _jsonFormatWriterDelegate = value; } } internal XmlDictionaryString[]? MemberNames { get { return _memberNames; } } internal ClassDataContract TraditionalClassDataContract { get { return _traditionalClassDataContract; } } private void CopyMembersAndCheckDuplicateNames() { if (_traditionalClassDataContract.MemberNames != null) { int memberCount = _traditionalClassDataContract.MemberNames.Length; Dictionary<string, object?> memberTable = new Dictionary<string, object?>(memberCount); XmlDictionaryString[] decodedMemberNames = new XmlDictionaryString[memberCount]; for (int i = 0; i < memberCount; i++) { if (memberTable.ContainsKey(_traditionalClassDataContract.MemberNames[i].Value)) { throw new SerializationException(SR.Format(SR.JsonDuplicateMemberNames, DataContract.GetClrTypeFullName(_traditionalClassDataContract.UnderlyingType), _traditionalClassDataContract.MemberNames[i].Value)); } else { memberTable.Add(_traditionalClassDataContract.MemberNames[i].Value, null); decodedMemberNames[i] = DataContractJsonSerializer.ConvertXmlNameToJsonName(_traditionalClassDataContract.MemberNames[i]); } } _memberNames = decodedMemberNames; } } } } }