private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int initialDepth = writer.Top; for (int index = 0; index < contract.Properties.Count; index++) { JsonProperty property = contract.Properties[index]; // only write non-dynamic properties that have an explicit attribute if (property.HasMemberAttribute) { try { object memberValue; JsonContract memberContract; if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue)) { continue; } property.WritePropertyName(writer); SerializeValue(writer, memberValue, memberContract, property, contract, member); } catch (Exception ex) { if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } } foreach (string memberName in value.GetDynamicMemberNames()) { object memberValue; if (contract.TryGetMember(value, memberName, out memberValue)) { try { JsonContract valueContract = GetContractSafe(memberValue); if (!ShouldWriteDynamicProperty(memberValue)) { continue; } if (CheckForCircularReference(writer, memberValue, null, valueContract, contract, member)) { string resolvedPropertyName = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(memberName) : memberName; writer.WritePropertyName(resolvedPropertyName); SerializeValue(writer, memberValue, valueContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(value, contract, memberName, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); }
private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty) { if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty)) { WriteReference(writer, value); } else { if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty)) { return; } _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, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { IWrappedCollection wrappedCollection = values as IWrappedCollection; object underlyingList = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : values; OnSerializing(writer, contract, underlyingList); _serializeStack.Add(underlyingList); bool hasWrittenMetadataObject = WriteStartArray(writer, underlyingList, contract, member, collectionContract, containerProperty); writer.WriteStartArray(); int initialDepth = writer.Top; int index = 0; // note that an error in the IEnumerable won't be caught foreach (object value in values) { try { JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { WriteReference(writer, value); } else { if (CheckForCircularReference(writer, value, null, valueContract, contract, member)) { SerializeValue(writer, value, valueContract, null, contract, member); } } } catch (Exception ex) { if (IsErrorHandled(underlyingList, contract, index, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } finally { index++; } } writer.WriteEndArray(); if (hasWrittenMetadataObject) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, underlyingList); }
private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, 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, 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 objectContract = contract as JsonObjectContract; Required resolvedRequired = property._required ?? ((objectContract != null) ? objectContract.ItemRequired : null) ?? Required.Default; if (resolvedRequired == 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); } if (resolvedRequired == 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 SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int initialDepth = writer.Top; for (int index = 0; index < contract.Properties.Count; index++) { JsonProperty property = contract.Properties[index]; try { object memberValue; JsonContract memberContract; if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue)) { continue; } property.WritePropertyName(writer); SerializeValue(writer, memberValue, memberContract, property, contract, member); } catch (Exception ex) { if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } if (contract.ExtensionDataGetter != null) { IEnumerable <KeyValuePair <object, object> > extensionData = contract.ExtensionDataGetter(value); if (extensionData != null) { foreach (KeyValuePair <object, object> e in extensionData) { JsonContract keyContract = GetContractSafe(e.Key); JsonContract valueContract = GetContractSafe(e.Value); bool escape; string propertyName = GetPropertyName(writer, e.Key, keyContract, out escape); if (ShouldWriteReference(e.Value, null, valueContract, contract, member)) { writer.WritePropertyName(propertyName); WriteReference(writer, e.Value); } else { if (!CheckForCircularReference(writer, e.Value, null, valueContract, contract, member)) { continue; } writer.WritePropertyName(propertyName); SerializeValue(writer, e.Value, valueContract, null, contract, member); } } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); }
private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) { return(true); } ReferenceLoopHandling?referenceLoopHandling = null; if (property != null) { referenceLoopHandling = property.ReferenceLoopHandling; } if (referenceLoopHandling == null && containerProperty != null) { referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; } if (referenceLoopHandling == null && containerContract != null) { referenceLoopHandling = containerContract.ItemReferenceLoopHandling; } bool exists = (Serializer._equalityComparer != null) ? _serializeStack.Contains(value, Serializer._equalityComparer) : _serializeStack.Contains(value); if (exists) { string message = "Self referencing loop detected"; if (property != null) { message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName); } message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()); switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling)) { case ReferenceLoopHandling.Error: throw JsonSerializationException.Create(null, writer.ContainerPath, message, null); case ReferenceLoopHandling.Ignore: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". 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, message + ". Serializing self referenced value."), null); } return(true); } } return(true); }
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null) { writer.WriteNull(); return; } JsonConverter converter = ((member != null) ? member.Converter : null) ?? ((containerProperty != null) ? containerProperty.ItemConverter : null) ?? ((containerContract != null) ? containerContract.ItemConverter : null) ?? valueContract.Converter ?? Serializer.GetMatchingConverter(valueContract.UnderlyingType) ?? valueContract.InternalConverter; if (converter != null && converter.CanWrite) { SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty); return; } switch (valueContract.ContractType) { case JsonContractType.Object: SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Array: JsonArrayContract arrayContract = (JsonArrayContract)valueContract; if (!arrayContract.IsMultidimensionalArray) { SerializeList(writer, (IEnumerable)value, arrayContract, member, containerContract, containerProperty); } else { SerializeMultidimensionalArray(writer, (Array)value, arrayContract, 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 dictionaryContract = (JsonDictionaryContract)valueContract; SerializeDictionary(writer, (value is IDictionary) ? (IDictionary)value : dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty); break; #if !(NET35 || NET20 || PORTABLE40) case JsonContractType.Dynamic: SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty); break; #endif #if !(DOTNET || PORTABLE40 || PORTABLE) case JsonContractType.Serializable: SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty); break; #endif case JsonContractType.Linq: ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray()); break; } }
private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { IWrappedDictionary wrappedDictionary = values as IWrappedDictionary; object underlyingDictionary = wrappedDictionary != null ? wrappedDictionary.UnderlyingDictionary : values; OnSerializing(writer, contract, underlyingDictionary); _serializeStack.Add(underlyingDictionary); WriteObjectStart(writer, underlyingDictionary, 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 initialDepth = writer.Top; foreach (DictionaryEntry entry in values) { bool escape; string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape); propertyName = (contract.DictionaryKeyResolver != null) ? contract.DictionaryKeyResolver(propertyName) : propertyName; try { object value = entry.Value; JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { writer.WritePropertyName(propertyName, escape); WriteReference(writer, value); } else { if (!CheckForCircularReference(writer, value, null, valueContract, contract, member)) { continue; } writer.WritePropertyName(propertyName, escape); SerializeValue(writer, value, valueContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, underlyingDictionary); }