JsonSerializerInternalWriter
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Newtonsoft.Json.Serialization
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
{
[System.Runtime.CompilerServices.Nullable(2)]
private Type _rootType;
private int _rootLevel;
private readonly List<object> _serializeStack = new List<object>();
public JsonSerializerInternalWriter(JsonSerializer serializer)
: base(serializer)
{
}
[System.Runtime.CompilerServices.NullableContext(2)]
public void Serialize([System.Runtime.CompilerServices.Nullable(1)] JsonWriter jsonWriter, object value, Type objectType)
{
if (jsonWriter == null)
throw new ArgumentNullException("jsonWriter");
_rootType = objectType;
_rootLevel = _serializeStack.Count + 1;
JsonContract contractSafe = GetContractSafe(value);
try {
if (ShouldWriteReference(value, null, contractSafe, null, null))
WriteReference(jsonWriter, value);
else
SerializeValue(jsonWriter, value, contractSafe, null, null, null);
} catch (Exception ex) {
if (!IsErrorHandled(null, contractSafe, null, null, jsonWriter.Path, ex)) {
ClearErrorContext();
throw;
}
HandleError(jsonWriter, 0);
} finally {
_rootType = null;
}
}
private JsonSerializerProxy GetInternalSerializer()
{
if (InternalSerializer == null)
InternalSerializer = new JsonSerializerProxy(this);
return InternalSerializer;
}
[System.Runtime.CompilerServices.NullableContext(2)]
private JsonContract GetContractSafe(object value)
{
if (value == null)
return null;
return GetContract(value);
}
private JsonContract GetContract(object value)
{
return Serializer._contractResolver.ResolveContract(value.GetType());
}
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract containerContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
if (contract.TypeCode == PrimitiveTypeCode.Bytes && ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty)) {
writer.WriteStartObject();
WriteTypeProperty(writer, contract.CreatedType);
writer.WritePropertyName("$value", false);
JsonWriter.WriteValue(writer, contract.TypeCode, value);
writer.WriteEndObject();
} else
JsonWriter.WriteValue(writer, contract.TypeCode, value);
}
[System.Runtime.CompilerServices.NullableContext(2)]
private void SerializeValue([System.Runtime.CompilerServices.Nullable(1)] JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
{
if (value == null)
writer.WriteNull();
else {
JsonConverter jsonConverter = member?.Converter ?? containerProperty?.ItemConverter ?? containerContract?.ItemConverter ?? valueContract.Converter ?? Serializer.GetMatchingConverter(valueContract.UnderlyingType) ?? valueContract.InternalConverter;
if (jsonConverter == null || !jsonConverter.CanWrite) {
switch (valueContract.ContractType) {
case JsonContractType.Serializable:
break;
case JsonContractType.Object:
SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty);
break;
case JsonContractType.Array: {
JsonArrayContract jsonArrayContract = (JsonArrayContract)valueContract;
if (!jsonArrayContract.IsMultidimensionalArray)
SerializeList(writer, (IEnumerable)value, jsonArrayContract, member, containerContract, containerProperty);
else
SerializeMultidimensionalArray(writer, (Array)value, jsonArrayContract, member, containerContract, containerProperty);
break;
}
case JsonContractType.Primitive:
SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty);
break;
case JsonContractType.String:
SerializeString(writer, value, (JsonStringContract)valueContract);
break;
case JsonContractType.Dictionary: {
JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)valueContract;
IDictionary dictionary = value as IDictionary;
object values;
if (dictionary == null) {
IDictionary dictionary2 = jsonDictionaryContract.CreateWrapper(value);
values = dictionary2;
} else
values = dictionary;
SerializeDictionary(writer, (IDictionary)values, jsonDictionaryContract, member, containerContract, containerProperty);
break;
}
case JsonContractType.Dynamic:
SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
break;
case JsonContractType.Linq:
((JToken)value).WriteTo(writer, Serializer.Converters.ToArray());
break;
}
} else
SerializeConvertable(writer, jsonConverter, value, valueContract, containerContract, containerProperty);
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool? ResolveIsReference([System.Runtime.CompilerServices.Nullable(1)] JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty)
{
bool? result = null;
if (property != null)
result = property.IsReference;
if (!result.HasValue && containerProperty != null)
result = containerProperty.ItemIsReference;
if (!result.HasValue && collectionContract != null)
result = collectionContract.ItemIsReference;
if (!result.HasValue)
result = contract.IsReference;
return result;
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty)
{
if (value == null)
return false;
if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String)
return false;
bool? nullable = ResolveIsReference(valueContract, property, collectionContract, containerProperty);
if (!nullable.HasValue)
nullable = ((valueContract.ContractType == JsonContractType.Array) ? new bool?(HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays)) : new bool?(HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects)));
if (!nullable.GetValueOrDefault())
return false;
return Serializer.GetReferenceResolver().IsReferenced(this, value);
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool ShouldWriteProperty(object memberValue, JsonObjectContract containerContract, [System.Runtime.CompilerServices.Nullable(1)] JsonProperty property)
{
if (memberValue == null && ResolvedNullValueHandling(containerContract, property) == NullValueHandling.Ignore)
return false;
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue()))
return false;
return true;
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool CheckForCircularReference([System.Runtime.CompilerServices.Nullable(1)] JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
{
if (value == null)
return true;
if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
return true;
ReferenceLoopHandling? nullable = null;
if (property != null)
nullable = property.ReferenceLoopHandling;
if (!nullable.HasValue && containerProperty != null)
nullable = containerProperty.ItemReferenceLoopHandling;
if (!nullable.HasValue && containerContract != null)
nullable = containerContract.ItemReferenceLoopHandling;
if ((Serializer._equalityComparer != null) ? _serializeStack.Contains(value, Serializer._equalityComparer) : _serializeStack.Contains(value)) {
string str = "Self referencing loop detected";
if (property != null)
str += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName);
str += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType());
switch (nullable.GetValueOrDefault(Serializer._referenceLoopHandling)) {
case ReferenceLoopHandling.Error:
throw JsonSerializationException.Create(null, writer.ContainerPath, str, null);
case ReferenceLoopHandling.Ignore:
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, str + ". Skipping serializing self referenced value."), null);
return false;
case ReferenceLoopHandling.Serialize:
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, str + ". Serializing self referenced value."), null);
return true;
}
}
return true;
}
private void WriteReference(JsonWriter writer, object value)
{
string reference = GetReference(writer, value);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference to Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, value.GetType())), null);
writer.WriteStartObject();
writer.WritePropertyName("$ref", false);
writer.WriteValue(reference);
writer.WriteEndObject();
}
private string GetReference(JsonWriter writer, object value)
{
try {
return Serializer.GetReferenceResolver().GetReference(this, value);
} catch (Exception ex) {
throw JsonSerializationException.Create(null, writer.ContainerPath, "Error writing object reference for '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), ex);
}
}
internal static bool TryConvertToString(object value, Type type, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out string s)
{
if (value is Guid || value is Uri || value is TimeSpan) {
s = value.ToString();
return true;
}
Type type2 = value as Type;
if ((object)type2 != null) {
s = type2.AssemblyQualifiedName;
return true;
}
s = null;
return false;
}
private void SerializeString(JsonWriter writer, object value, JsonStringContract contract)
{
OnSerializing(writer, contract, value);
TryConvertToString(value, contract.UnderlyingType, out string s);
writer.WriteValue(s);
OnSerialized(writer, contract, value);
}
private void OnSerializing(JsonWriter writer, JsonContract contract, object value)
{
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
contract.InvokeOnSerializing(value, Serializer._context);
}
private void OnSerialized(JsonWriter writer, JsonContract contract, object value)
{
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
contract.InvokeOnSerialized(value, Serializer._context);
}
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
OnSerializing(writer, contract, value);
_serializeStack.Add(value);
WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
int top = writer.Top;
for (int i = 0; i < contract.Properties.Count; i++) {
JsonProperty jsonProperty = contract.Properties[i];
try {
if (CalculatePropertyValues(writer, value, contract, member, jsonProperty, out JsonContract memberContract, out object memberValue)) {
jsonProperty.WritePropertyName(writer);
SerializeValue(writer, memberValue, memberContract, jsonProperty, contract, member);
}
} catch (Exception ex) {
if (!IsErrorHandled(value, contract, jsonProperty.PropertyName, null, writer.ContainerPath, ex))
throw;
HandleError(writer, top);
}
}
IEnumerable<KeyValuePair<object, object>> enumerable = contract.ExtensionDataGetter?.Invoke(value);
if (enumerable != null) {
foreach (KeyValuePair<object, object> item in enumerable) {
JsonContract contract2 = GetContract(item.Key);
JsonContract contractSafe = GetContractSafe(item.Value);
string propertyName = GetPropertyName(writer, item.Key, contract2, out bool _);
propertyName = ((contract.ExtensionDataNameResolver != null) ? contract.ExtensionDataNameResolver(propertyName) : propertyName);
if (ShouldWriteReference(item.Value, null, contractSafe, contract, member)) {
writer.WritePropertyName(propertyName);
WriteReference(writer, item.Value);
} else if (CheckForCircularReference(writer, item.Value, null, contractSafe, contract, member)) {
writer.WritePropertyName(propertyName);
SerializeValue(writer, item.Value, contractSafe, null, contract, member);
}
}
}
writer.WriteEndObject();
_serializeStack.RemoveAt(_serializeStack.Count - 1);
OnSerialized(writer, contract, value);
}
private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, JsonProperty property, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonContract memberContract, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out object memberValue)
{
if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value)) {
if (property.PropertyContract == null)
property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType);
memberValue = property.ValueProvider.GetValue(value);
memberContract = (property.PropertyContract.IsSealed ? property.PropertyContract : GetContractSafe(memberValue));
if (ShouldWriteProperty(memberValue, contract as JsonObjectContract, property)) {
if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) {
property.WritePropertyName(writer);
WriteReference(writer, memberValue);
return false;
}
if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member))
return false;
if (memberValue == null) {
JsonObjectContract jsonObjectContract = contract as JsonObjectContract;
switch (property._required ?? (jsonObjectContract?.ItemRequired).GetValueOrDefault()) {
case Required.Always:
throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
case Required.DisallowNull:
throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
}
}
return true;
}
}
memberContract = null;
memberValue = null;
return false;
}
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
writer.WriteStartObject();
if ((ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects)) && (member == null || member.Writable || HasCreatorParameter(collectionContract, member)))
WriteReferenceIdProperty(writer, contract.UnderlyingType, value);
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty))
WriteTypeProperty(writer, contract.UnderlyingType);
}
private bool HasCreatorParameter([System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract contract, JsonProperty property)
{
return (contract as JsonObjectContract)?.CreatorParameters.Contains(property.PropertyName) ?? false;
}
private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value)
{
string reference = GetReference(writer, value);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, type)), null);
writer.WritePropertyName("$id", false);
writer.WriteValue(reference);
}
private void WriteTypeProperty(JsonWriter writer, Type type)
{
string typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormatHandling, Serializer._serializationBinder);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing type name '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, typeName, type)), null);
writer.WritePropertyName("$type", false);
writer.WriteValue(typeName);
}
private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
{
return (value & flag) == flag;
}
private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag)
{
return (value & flag) == flag;
}
private bool HasFlag(TypeNameHandling value, TypeNameHandling flag)
{
return (value & flag) == flag;
}
private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty))
WriteReference(writer, value);
else if (CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty)) {
_serializeStack.Add(value);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
converter.WriteJson(writer, value, GetInternalSerializer());
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
_serializeStack.RemoveAt(_serializeStack.Count - 1);
}
}
private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
IWrappedCollection wrappedCollection = values as IWrappedCollection;
object obj = (wrappedCollection != null) ? wrappedCollection.UnderlyingCollection : values;
OnSerializing(writer, contract, obj);
_serializeStack.Add(obj);
bool flag = WriteStartArray(writer, obj, contract, member, collectionContract, containerProperty);
writer.WriteStartArray();
int top = writer.Top;
int num = 0;
foreach (object value in values) {
try {
JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value);
if (ShouldWriteReference(value, null, jsonContract, contract, member))
WriteReference(writer, value);
else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) {
SerializeValue(writer, value, jsonContract, null, contract, member);
}
} catch (Exception ex) {
if (!IsErrorHandled(obj, contract, num, null, writer.ContainerPath, ex))
throw;
HandleError(writer, top);
} finally {
num++;
}
}
writer.WriteEndArray();
if (flag)
writer.WriteEndObject();
_serializeStack.RemoveAt(_serializeStack.Count - 1);
OnSerialized(writer, contract, obj);
}
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
OnSerializing(writer, contract, values);
_serializeStack.Add(values);
bool num = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);
SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, CollectionUtils.ArrayEmpty<int>());
if (num)
writer.WriteEndObject();
_serializeStack.RemoveAt(_serializeStack.Count - 1);
OnSerialized(writer, contract, values);
}
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, int initialDepth, int[] indices)
{
int num = indices.Length;
int[] array = new int[num + 1];
for (int i = 0; i < num; i++) {
array[i] = indices[i];
}
writer.WriteStartArray();
for (int j = values.GetLowerBound(num); j <= values.GetUpperBound(num); j++) {
array[num] = j;
if (array.Length == values.Rank) {
object value = values.GetValue(array);
try {
JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value);
if (ShouldWriteReference(value, null, jsonContract, contract, member))
WriteReference(writer, value);
else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) {
SerializeValue(writer, value, jsonContract, null, contract, member);
}
} catch (Exception ex) {
if (!IsErrorHandled(values, contract, j, null, writer.ContainerPath, ex))
throw;
HandleError(writer, initialDepth + 1);
}
} else
SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, array);
}
writer.WriteEndArray();
}
private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract containerContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
bool flag = (ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays)) && (member == null || member.Writable || HasCreatorParameter(containerContract, member));
bool flag2 = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
bool num = flag | flag2;
if (num) {
writer.WriteStartObject();
if (flag)
WriteReferenceIdProperty(writer, contract.UnderlyingType, values);
if (flag2)
WriteTypeProperty(writer, values.GetType());
writer.WritePropertyName("$values", false);
}
if (contract.ItemContract == null)
contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object));
return num;
}
private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
OnSerializing(writer, contract, value);
_serializeStack.Add(value);
WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
int top = writer.Top;
for (int i = 0; i < contract.Properties.Count; i++) {
JsonProperty jsonProperty = contract.Properties[i];
if (jsonProperty.HasMemberAttribute)
try {
if (CalculatePropertyValues(writer, value, contract, member, jsonProperty, out JsonContract memberContract, out object memberValue)) {
jsonProperty.WritePropertyName(writer);
SerializeValue(writer, memberValue, memberContract, jsonProperty, contract, member);
}
} catch (Exception ex) {
if (!IsErrorHandled(value, contract, jsonProperty.PropertyName, null, writer.ContainerPath, ex))
throw;
HandleError(writer, top);
}
}
foreach (string dynamicMemberName in value.GetDynamicMemberNames()) {
if (contract.TryGetMember(value, dynamicMemberName, out object value2))
try {
JsonContract contractSafe = GetContractSafe(value2);
if (ShouldWriteDynamicProperty(value2) && CheckForCircularReference(writer, value2, null, contractSafe, contract, member)) {
string name = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(dynamicMemberName) : dynamicMemberName;
writer.WritePropertyName(name);
SerializeValue(writer, value2, contractSafe, null, contract, member);
}
} catch (Exception ex2) {
if (!IsErrorHandled(value, contract, dynamicMemberName, null, writer.ContainerPath, ex2))
throw;
HandleError(writer, top);
}
}
writer.WriteEndObject();
_serializeStack.RemoveAt(_serializeStack.Count - 1);
OnSerialized(writer, contract, value);
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool ShouldWriteDynamicProperty(object memberValue)
{
if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null)
return false;
if (HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Ignore) && (memberValue == null || MiscellaneousUtils.ValueEquals(memberValue, ReflectionUtils.GetDefaultValue(memberValue.GetType()))))
return false;
return true;
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, [System.Runtime.CompilerServices.Nullable(1)] JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
{
TypeNameHandling value = member?.TypeNameHandling ?? containerProperty?.ItemTypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? Serializer._typeNameHandling;
if (HasFlag(value, typeNameHandlingFlag))
return true;
if (HasFlag(value, TypeNameHandling.Auto)) {
if (member != null) {
if ((object)contract.NonNullableUnderlyingType != member.PropertyContract.CreatedType)
return true;
} else if (containerContract != null) {
if (containerContract.ItemContract == null || (object)contract.NonNullableUnderlyingType != containerContract.ItemContract.CreatedType)
return true;
} else if ((object)_rootType != null && _serializeStack.Count == _rootLevel) {
JsonContract jsonContract = Serializer._contractResolver.ResolveContract(_rootType);
if ((object)contract.NonNullableUnderlyingType != jsonContract.CreatedType)
return true;
}
}
return false;
}
private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty member, [System.Runtime.CompilerServices.Nullable(2)] JsonContainerContract collectionContract, [System.Runtime.CompilerServices.Nullable(2)] JsonProperty containerProperty)
{
IWrappedDictionary wrappedDictionary = values as IWrappedDictionary;
object obj = (wrappedDictionary != null) ? wrappedDictionary.UnderlyingDictionary : values;
OnSerializing(writer, contract, obj);
_serializeStack.Add(obj);
WriteObjectStart(writer, obj, contract, member, collectionContract, containerProperty);
if (contract.ItemContract == null)
contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
if (contract.KeyContract == null)
contract.KeyContract = Serializer._contractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object));
int top = writer.Top;
IDictionaryEnumerator enumerator = values.GetEnumerator();
try {
while (enumerator.MoveNext()) {
DictionaryEntry entry = enumerator.Entry;
string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out bool escape);
propertyName = ((contract.DictionaryKeyResolver != null) ? contract.DictionaryKeyResolver(propertyName) : propertyName);
try {
object value = entry.Value;
JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value);
if (ShouldWriteReference(value, null, jsonContract, contract, member)) {
writer.WritePropertyName(propertyName, escape);
WriteReference(writer, value);
} else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) {
writer.WritePropertyName(propertyName, escape);
SerializeValue(writer, value, jsonContract, null, contract, member);
}
} catch (Exception ex) {
if (!IsErrorHandled(obj, contract, propertyName, null, writer.ContainerPath, ex))
throw;
HandleError(writer, top);
}
}
} finally {
(enumerator as IDisposable)?.Dispose();
}
writer.WriteEndObject();
_serializeStack.RemoveAt(_serializeStack.Count - 1);
OnSerialized(writer, contract, obj);
}
private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape)
{
if (contract.ContractType == JsonContractType.Primitive) {
JsonPrimitiveContract jsonPrimitiveContract = (JsonPrimitiveContract)contract;
switch (jsonPrimitiveContract.TypeCode) {
case PrimitiveTypeCode.DateTime:
case PrimitiveTypeCode.DateTimeNullable: {
DateTime value = DateTimeUtils.EnsureDateTime((DateTime)name, writer.DateTimeZoneHandling);
escape = false;
StringWriter stringWriter2 = new StringWriter(CultureInfo.InvariantCulture);
DateTimeUtils.WriteDateTimeString(stringWriter2, value, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
return stringWriter2.ToString();
}
case PrimitiveTypeCode.DateTimeOffset:
case PrimitiveTypeCode.DateTimeOffsetNullable: {
escape = false;
StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
DateTimeUtils.WriteDateTimeOffsetString(stringWriter, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
return stringWriter.ToString();
}
case PrimitiveTypeCode.Double:
case PrimitiveTypeCode.DoubleNullable: {
double num = (double)name;
escape = false;
return num.ToString("R", CultureInfo.InvariantCulture);
}
case PrimitiveTypeCode.Single:
case PrimitiveTypeCode.SingleNullable: {
float num2 = (float)name;
escape = false;
return num2.ToString("R", CultureInfo.InvariantCulture);
}
default:
escape = true;
if (jsonPrimitiveContract.IsEnum && EnumUtils.TryToString(jsonPrimitiveContract.NonNullableUnderlyingType, name, null, out string name2))
return name2;
return Convert.ToString(name, CultureInfo.InvariantCulture);
}
}
if (TryConvertToString(name, name.GetType(), out string s)) {
escape = true;
return s;
}
escape = true;
return name.ToString();
}
private void HandleError(JsonWriter writer, int initialDepth)
{
ClearErrorContext();
if (writer.WriteState == WriteState.Property)
writer.WriteNull();
while (writer.Top > initialDepth) {
writer.WriteEnd();
}
}
private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target)
{
if (property.ShouldSerialize == null)
return true;
bool flag = property.ShouldSerialize(target);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null);
return flag;
}
private bool IsSpecified(JsonWriter writer, JsonProperty property, object target)
{
if (property.GetIsSpecified == null)
return true;
bool flag = property.GetIsSpecified(target);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null);
return flag;
}
}
}