private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (contract.UnderlyingType == typeof (byte[])) { bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty); if (includeTypeDetails) { writer.WriteStartObject(); WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName(JsonTypeReflector.ValuePropertyName); writer.WriteValue(value); writer.WriteEndObject(); return; } } writer.WriteValue(value); }
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); } } } } if (beforeClosingObject != null) beforeClosingObject(value, writer); writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); }
private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id) { object list = wrappedList.UnderlyingCollection; if (id != null) Serializer.ReferenceResolver.AddReference(this, id, list); // can't populate an existing array if (wrappedList.IsFixedSize) { reader.Skip(); return list; } contract.InvokeOnDeserializing(list, Serializer.Context); int initialDepth = reader.Depth; JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType); JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty); int? previousErrorIndex = null; while (true) { try { if (ReadForType(reader, collectionItemContract, collectionItemConverter != null)) { switch (reader.TokenType) { case JsonToken.EndArray: contract.InvokeOnDeserialized(list, Serializer.Context); return list; case JsonToken.Comment: break; default: object value; if (collectionItemConverter != null && collectionItemConverter.CanRead) value = collectionItemConverter.ReadJson(reader, contract.CollectionItemType, null, GetInternalSerializer()); else value = CreateValueInternal(reader, contract.CollectionItemType, collectionItemContract, null, contract, containerProperty, null); wrappedList.Add(value); break; } } else { break; } } catch (Exception ex) { JsonPosition errorPosition = reader.GetPosition(initialDepth); if (IsErrorHandled(list, contract, errorPosition.Position, reader.Path, ex)) { HandleError(reader, true, initialDepth); if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position) { // reader index has not moved since previous error handling // break out of reading array to prevent infinite loop throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); } else { previousErrorIndex = errorPosition.Position; } } else { throw; } } } throw JsonSerializationException.Create(reader, "Unexpected end when deserializing array."); }
private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target) { if (property.ShouldSerialize == null) return true; bool shouldSerialize = 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, shouldSerialize)), null); return shouldSerialize; }
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 SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { OnSerializing(writer, contract, values); _serializeStack.Add(values); bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty); SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]); if (hasWrittenMetadataObject) writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, values); }
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); } return true; } } memberContract = null; memberValue = null; return false; }
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? isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty); if (isReference == null) { if (valueContract.ContractType == JsonContractType.Array) isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays); else isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects); } if (!isReference.Value) return false; return Serializer.GetReferenceResolver().IsReferenced(this, value); }
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices) { int dimension = indices.Length; int[] newIndices = new int[dimension + 1]; for (int i = 0; i < dimension; i++) { newIndices[i] = indices[i]; } writer.WriteStartArray(); for (int i = 0; i < values.GetLength(dimension); i++) { newIndices[dimension] = i; bool isTopLevel = (newIndices.Length == values.Rank); if (isTopLevel) { object value = values.GetValue(newIndices); 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(values, contract, i, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth + 1); } else { throw; } } } else { SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices); } } writer.WriteEndArray(); }
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { OnSerializing(writer, contract, values); _serializeStack.Add(values); bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty); SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]); if (hasWrittenMetadataObject) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, values); }
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; IEnumerator enumerator; try { enumerator = values.GetEnumerator(); } catch (Exception e) { throw new InvalidOperationException("Could not get enumerator for property: " + member, e); } using (enumerator as IDisposable) { while (true) { try { if (enumerator.MoveNext() == false) { break; } } catch (Exception e) { throw new InvalidOperationException("Could not move to next value for property: " + member, e); } object value; try { value = enumerator.Current; } catch (Exception e) { throw new InvalidOperationException("Could not get current value for property: " + member, e); } 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 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 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); } } 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 (beforeClosingObject != null) { beforeClosingObject(value, writer); } 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; } if (_serializeStack.IndexOf(value) != -1) { 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 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; IEnumerator enumerator; try { enumerator = values.GetEnumerator(); } catch (Exception e) { throw new InvalidOperationException("Could not get enumerator for property: " + member, e); } using (enumerator as IDisposable) { while (true) { try { if (enumerator.MoveNext() == false) break; } catch (Exception e) { throw new InvalidOperationException("Could not move to next value for property: " + member, e); } object value; try { value = enumerator.Current; } catch (Exception e) { throw new InvalidOperationException("Could not get current value for property: " + member, e); } 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 void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null) { writer.WriteNull(); return; } JsonConverter converter; if ((((converter = (member != null) ? member.Converter : null) != null) || ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null) || ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null) || ((converter = valueContract.Converter) != null) || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null) || ((converter = valueContract.InternalConverter) != 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 !(SILVERLIGHT || NETFX_CORE || 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 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 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; if (_serializeStack.IndexOf(value) != -1) { 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; if ((((converter = (member != null) ? member.Converter : null) != null) || ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null) || ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null) || ((converter = valueContract.Converter) != null) || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null) || ((converter = valueContract.InternalConverter) != 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; SerializeList(writer, arrayContract.CreateWrapper(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, dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty); break; #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) case JsonContractType.Dynamic: SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty); break; #endif #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) case JsonContractType.Serializable: SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty); break; #endif case JsonContractType.Linq: ((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null); break; } }
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 bool?ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty) { bool?isReference = null; // value could be coming from a dictionary or array and not have a property if (property != null) { isReference = property.IsReference; } if (isReference == null && containerProperty != null) { isReference = containerProperty.ItemIsReference; } if (isReference == null && collectionContract != null) { isReference = collectionContract.ItemIsReference; } if (isReference == null) { isReference = contract.IsReference; } return(isReference); }
private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays); bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty); bool writeMetadataObject = isReference || includeTypeDetails; if (writeMetadataObject) { writer.WriteStartObject(); if (isReference) { WriteReferenceIdProperty(writer, contract.UnderlyingType, values); } if (includeTypeDetails) { WriteTypeProperty(writer, values.GetType()); } writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName, false); } if (contract.ItemContract == null) contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object)); return writeMetadataObject; }
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?isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty); if (isReference == null) { if (valueContract.ContractType == JsonContractType.Array) { isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); } else { isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); } } if (!isReference.Value) { return(false); } return(Serializer.ReferenceResolver.IsReferenced(this, value)); }
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, contract.KeyContract, out escape); propertyName = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(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); }
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; } if (_serializeStack.IndexOf(value) != -1) { switch (referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling)) { case ReferenceLoopHandling.Error: 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()); throw JsonSerializationException.Create(null, writer.ContainerPath, message, null); case ReferenceLoopHandling.Ignore: return(false); case ReferenceLoopHandling.Serialize: return(true); default: throw new InvalidOperationException("Unexpected ReferenceLoopHandling value: '{0}'".FormatWith(CultureInfo.InvariantCulture, Serializer.ReferenceLoopHandling)); } } return(true); }
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, contract.KeyContract, out escape); propertyName = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(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); }
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int initialDepth = writer.Top; foreach (JsonProperty property in contract.Properties) { try { if (!property.Ignored && property.Readable && ShouldSerialize(property, value) && IsSpecified(property, value)) { if (property.PropertyContract == null) { property.PropertyContract = Serializer.ContractResolver.ResolveContract(property.PropertyType); } object memberValue = property.ValueProvider.GetValue(value); JsonContract memberContract = (property.PropertyContract.UnderlyingType.IsSealed()) ? property.PropertyContract : GetContractSafe(memberValue); if (ShouldWriteProperty(memberValue, property)) { string propertyName = property.PropertyName; if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) { writer.WritePropertyName(propertyName); WriteReference(writer, memberValue); continue; } if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member)) { continue; } if (memberValue == null) { Required resolvedRequired = property._required ?? contract.ItemRequired ?? 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); } } writer.WritePropertyName(propertyName); SerializeValue(writer, memberValue, memberContract, property, contract, member); } } } catch (Exception ex) { if (IsErrorHandled(value, contract, property.PropertyName, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(value, Serializer.Context); }
private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty member, string id) { IDynamicMetaObjectProvider newObject; if (contract.UnderlyingType.IsInterface() || contract.UnderlyingType.IsAbstract()) throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) newObject = (IDynamicMetaObjectProvider) contract.DefaultCreator(); else throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); if (id != null) Serializer.ReferenceResolver.AddReference(this, id, newObject); contract.InvokeOnDeserializing(newObject, Serializer.Context); int initialDepth = reader.Depth; bool exit = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: string memberName = reader.Value.ToString(); try { if (!reader.Read()) throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); // first attempt to find a settable property, otherwise fall back to a dynamic set without type JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName); if (property != null && property.Writable && !property.Ignored) { if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, null, null); SetPropertyValue(property, propertyConverter, null, member, reader, newObject); } else { Type t = (JsonReader.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType : typeof (IDynamicMetaObjectProvider); JsonContract dynamicMemberContract = GetContractSafe(t); JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null, member); object value; if (dynamicMemberConverter != null && dynamicMemberConverter.CanRead) value = dynamicMemberConverter.ReadJson(reader, t, null, GetInternalSerializer()); else value = CreateValueInternal(reader, t, dynamicMemberContract, null, null, member, null); newObject.TrySetMember(memberName, value); } } catch (Exception ex) { if (IsErrorHandled(newObject, contract, memberName, reader.Path, ex)) HandleError(reader, true, initialDepth); else throw; } break; case JsonToken.EndObject: exit = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); } } while (!exit && reader.Read()); contract.InvokeOnDeserialized(newObject, Serializer.Context); return newObject; }
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { writer.WriteStartObject(); bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); if (isReference) { writer.WritePropertyName(JsonTypeReflector.IdPropertyName); writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value)); } if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) { WriteTypeProperty(writer, contract.UnderlyingType); } }
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { writer.WriteStartObject(); bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects); // don't make readonly fields the referenced value because they can't be deserialized to if (isReference && (member == null || member.Writable)) { WriteReferenceIdProperty(writer, contract.UnderlyingType, value); } if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) { WriteTypeProperty(writer, contract.UnderlyingType); } }
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); converter.WriteJson(writer, value, GetInternalSerializer()); _serializeStack.RemoveAt(_serializeStack.Count - 1); } }
private static bool ShouldSimplifyJsonBasedOnType(string typeValue, JsonProperty jsonProperty) { if (jsonProperty != null && (jsonProperty.TypeNameHandling == TypeNameHandling.All || jsonProperty.TypeNameHandling == TypeNameHandling.Arrays)) return false; // explicitly rejected what we are trying to do here if (typeValue == null) return false; if (typeValue.StartsWith("System.Collections.Generic.List`1[[")) return true; if (typeValue.StartsWith("System.Collections.Generic.Dictionary`2[[")) return true; if (arrayEndRegex.IsMatch(typeValue)) // array return true; return false; }
private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(values.UnderlyingCollection, Serializer.Context); _serializeStack.Add(values.UnderlyingCollection); bool hasWrittenMetadataObject = WriteStartArray(writer, values, 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(values.UnderlyingCollection, contract, index, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } finally { index++; } } writer.WriteEndArray(); if (hasWrittenMetadataObject) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context); }
private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty) { bool? isReference = null; // value could be coming from a dictionary or array and not have a property if (property != null) isReference = property.IsReference; if (isReference == null && containerProperty != null) isReference = containerProperty.ItemIsReference; if (isReference == null && collectionContract != null) isReference = collectionContract.ItemIsReference; if (isReference == null) isReference = contract.IsReference; return isReference; }
private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty); bool writeMetadataObject = isReference || includeTypeDetails; if (writeMetadataObject) { writer.WriteStartObject(); if (isReference) { writer.WritePropertyName(JsonTypeReflector.IdPropertyName); writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingCollection)); } if (includeTypeDetails) { WriteTypeProperty(writer, values.UnderlyingCollection.GetType()); } writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName); } if (contract.ItemContract == null) { contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object)); } return(writeMetadataObject); }
private bool ShouldWriteProperty(object memberValue, JsonProperty property) { if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && memberValue == null) return false; if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue())) return false; return true; }
private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { if (!JsonTypeReflector.FullyTrusted) { throw JsonSerializationException.Create(null, writer.ContainerPath, @"Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data. To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); value.GetObjectData(serializationInfo, Serializer.Context); foreach (SerializationEntry serializationEntry in serializationInfo) { writer.WritePropertyName(serializationEntry.Name); SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null, member); } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(value, Serializer.Context); }
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 (beforeClosingObject != null) beforeClosingObject(value, writer); writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); }
private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); foreach (string memberName in value.GetDynamicMemberNames()) { object memberValue; if (DynamicUtils.TryGetMember(value, memberName, out memberValue)) { string resolvedPropertyName = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(memberName) : memberName; writer.WritePropertyName(resolvedPropertyName); SerializeValue(writer, memberValue, GetContractSafe(memberValue), null, null, member); } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(value, Serializer.Context); }
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { writer.WriteStartObject(); bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects); if (isReference) { WriteReferenceIdProperty(writer, contract.UnderlyingType, value); } if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) { WriteTypeProperty(writer, contract.UnderlyingType); } }
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null) ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null) ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null) ?? Serializer.TypeNameHandling; if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag)) { return(true); } // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default) if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto)) { if (member != null) { if (contract.UnderlyingType != member.PropertyContract.CreatedType) { return(true); } } else if (containerContract != null && containerContract.ItemContract != null) { if (contract.UnderlyingType != containerContract.ItemContract.CreatedType) { return(true); } } } return(false); }
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 void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context); _serializeStack.Add(values.UnderlyingDictionary); WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract, containerProperty); if (contract.ItemContract == null) { contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); } int initialDepth = writer.Top; // Mono Unity 3.0 fix IWrappedDictionary d = values; foreach (DictionaryEntry entry in d) { string propertyName = GetPropertyName(entry); propertyName = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(propertyName) : propertyName; try { object value = entry.Value; JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { writer.WritePropertyName(propertyName); WriteReference(writer, value); } else { if (!CheckForCircularReference(writer, value, null, valueContract, contract, member)) { continue; } writer.WritePropertyName(propertyName); SerializeValue(writer, value, valueContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); contract.InvokeOnSerialized(values.UnderlyingDictionary, Serializer.Context); }
private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices) { int dimension = indices.Length; int[] newIndices = new int[dimension + 1]; for (int i = 0; i < dimension; i++) { newIndices[i] = indices[i]; } writer.WriteStartArray(); for (int i = 0; i < values.GetLength(dimension); i++) { newIndices[dimension] = i; bool isTopLevel = (newIndices.Length == values.Rank); if (isTopLevel) { object value = values.GetValue(newIndices); 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(values, contract, i, null, writer.ContainerPath, ex)) HandleError(writer, initialDepth + 1); else throw; } } else { SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices); } } writer.WriteEndArray(); }
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (contract.UnderlyingType == typeof(byte[])) { bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty); if (includeTypeDetails) { writer.WriteStartObject(); WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName(JsonTypeReflector.ValuePropertyName); writer.WriteValue(value); writer.WriteEndObject(); return; } } writer.WriteValue(value); }
private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { if (!JsonTypeReflector.FullyTrusted) { throw JsonSerializationException.Create(null, writer.ContainerPath, @"Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data. To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); value.GetObjectData(serializationInfo, Serializer._context); foreach (SerializationEntry serializationEntry in serializationInfo) { JsonContract valueContract = GetContractSafe(serializationEntry.Value); if (CheckForCircularReference(writer, serializationEntry.Value, null, valueContract, contract, member)) { writer.WritePropertyName(serializationEntry.Name); SerializeValue(writer, serializationEntry.Value, valueContract, null, contract, member); } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); }
private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue) { currentValue = null; useExistingValue = false; propertyContract = null; gottenCurrentValue = false; if (property.Ignored) { reader.Skip(); return true; } ObjectCreationHandling objectCreationHandling = property.ObjectCreationHandling.GetValueOrDefault(Serializer.ObjectCreationHandling); if ((objectCreationHandling == ObjectCreationHandling.Auto || objectCreationHandling == ObjectCreationHandling.Reuse) && (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject) && property.Readable) { currentValue = property.ValueProvider.GetValue(target); gottenCurrentValue = true; useExistingValue = (currentValue != null && !property.PropertyType.IsArray && !ReflectionUtils.InheritsGenericDefinition(property.PropertyType, typeof (ReadOnlyCollection<>)) && !property.PropertyType.IsValueType()); } if (!property.Writable && !useExistingValue) { reader.Skip(); return true; } // test tokentype here because null might not be convertable to some types, e.g. ignoring null when applied to DateTime if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && reader.TokenType == JsonToken.Null) { reader.Skip(); return true; } // test tokentype here because default value might not be convertable to actual type, e.g. default of "" for DateTime if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) && JsonReader.IsPrimitiveToken(reader.TokenType) && MiscellaneousUtils.ValueEquals(reader.Value, property.DefaultValue)) { reader.Skip(); return true; } if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); if (currentValue == null) { propertyContract = property.PropertyContract; } else { propertyContract = GetContractSafe(currentValue.GetType()); if (propertyContract != property.PropertyContract) propertyConverter = GetConverter(propertyContract, property.MemberConverter, containerContract, containerProperty); } return false; }
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null) ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null) ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null) ?? Serializer._typeNameHandling; if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag)) return true; // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default) if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto)) { if (member != null) { if (contract.UnderlyingType != member.PropertyContract.CreatedType) return true; } else if (containerContract != null) { if (containerContract.ItemContract == null || contract.UnderlyingType != containerContract.ItemContract.CreatedType) return true; } else if (_rootContract != null && _serializeStack.Count == 1) { if (contract.UnderlyingType != _rootContract.CreatedType) return true; } } return false; }
private bool ShouldSetPropertyValue(JsonProperty property, object value) { if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && value == null) return false; if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) && MiscellaneousUtils.ValueEquals(value, property.DefaultValue)) return false; if (!property.Writable) return false; return true; }
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (contract.TypeCode == PrimitiveTypeCode.Bytes) { // if type name handling is enabled then wrap the base64 byte string in an object with the type name bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty); if (includeTypeDetails) { writer.WriteStartObject(); WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName(JsonTypeReflector.ValuePropertyName, false); JsonWriter.WriteValue(writer, contract.TypeCode, value); writer.WriteEndObject(); return; } } JsonWriter.WriteValue(writer, contract.TypeCode, value); }
private object PopulateDictionary(IWrappedDictionary wrappedDictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty containerProperty, string id) { object dictionary = wrappedDictionary.UnderlyingDictionary; if (id != null) Serializer.ReferenceResolver.AddReference(this, id, dictionary); contract.InvokeOnDeserializing(dictionary, Serializer.Context); int initialDepth = reader.Depth; if (contract.KeyContract == null) contract.KeyContract = GetContractSafe(contract.DictionaryKeyType); if (contract.ItemContract == null) contract.ItemContract = GetContractSafe(contract.DictionaryValueType); JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); do { switch (reader.TokenType) { case JsonToken.PropertyName: object keyValue = reader.Value; try { try { keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex); } if (!ReadForType(reader, contract.ItemContract, dictionaryValueConverter != null)) throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); object itemValue; if (dictionaryValueConverter != null && dictionaryValueConverter.CanRead) itemValue = dictionaryValueConverter.ReadJson(reader, contract.DictionaryValueType, null, GetInternalSerializer()); else itemValue = CreateValueInternal(reader, contract.DictionaryValueType, contract.ItemContract, null, contract, containerProperty, null); wrappedDictionary[keyValue] = itemValue; } catch (Exception ex) { if (IsErrorHandled(dictionary, contract, keyValue, reader.Path, ex)) HandleError(reader, true, initialDepth); else throw; } break; case JsonToken.Comment: break; case JsonToken.EndObject: contract.InvokeOnDeserialized(dictionary, Serializer.Context); return dictionary; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); }
private bool IsSpecified(JsonWriter writer, JsonProperty property, object target) { if (property.GetIsSpecified == null) return true; bool isSpecified = 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, isSpecified)), null); return isSpecified; }