public void Serialize(JsonWriter jsonWriter, object value, Type objectType) { if (jsonWriter == null) throw new ArgumentNullException("jsonWriter"); if (objectType != null) _rootContract = Serializer._contractResolver.ResolveContract(objectType); SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null); }
public void Serialize(JsonWriter jsonWriter, object value, Type objectType) { if (jsonWriter == null) throw new ArgumentNullException("jsonWriter"); _rootContract = (objectType != null) ? Serializer._contractResolver.ResolveContract(objectType) : null; _rootLevel = _serializeStack.Count + 1; _internalConverters = Serializer.Converters; JsonContract contract = GetContractSafe(value); try { if (ShouldWriteReference(value, null, contract, null, null)) { WriteReference(jsonWriter, value); } else { SerializeValue(jsonWriter, value, contract, null, null, null); } } catch (Exception ex) { if (IsErrorHandled(null, contract, null, null, jsonWriter.Path, ex)) { HandleError(jsonWriter, 0); } else { // clear context in case serializer is being used inside a converter // if the converter wraps the error then not clearing the context will cause this error: // "Current error context error is different to requested error." ClearErrorContext(); throw; } } finally { // clear root contract to ensure that if level was > 1 then it won't // accidently be used for non root values _rootContract = null; } }
private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape) { string propertyName; if (contract.ContractType == JsonContractType.Primitive) { JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract; if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable) { escape = false; StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeString(sw, (DateTime)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return sw.ToString(); } #if !NET20 else if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffset || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffsetNullable) { escape = false; StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return sw.ToString(); } #endif else { escape = true; return Convert.ToString(name, CultureInfo.InvariantCulture); } } else if (TryConvertToString(name, name.GetType(), out propertyName)) { escape = true; return propertyName; } else { escape = true; return name.ToString(); } }
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 object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string id) { object value; if (HasDefinedType(objectType)) { JsonArrayContract arrayContract = EnsureArrayContract(reader, objectType, contract); if (existingValue == null) { bool isTemporaryListReference; IList list = CollectionUtils.CreateList(contract.CreatedType, out isTemporaryListReference); if (id != null && isTemporaryListReference) throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); #if !PocketPC if (contract.OnSerializing != null && isTemporaryListReference) throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); #endif if (contract.OnError != null && isTemporaryListReference) throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); PopulateList(arrayContract.CreateWrapper(list), reader, arrayContract, member, id); // create readonly and fixed sized collections using the temporary list if (isTemporaryListReference) { if (contract.CreatedType.IsArray) list = CollectionUtils.ToArray(((List<object>)list).ToArray(), ReflectionUtils.GetCollectionItemType(contract.CreatedType)); else if (ReflectionUtils.InheritsGenericDefinition(contract.CreatedType, typeof(ReadOnlyCollection<>))) list = (IList)ReflectionUtils.CreateInstance(contract.CreatedType, list); } else if (list is IWrappedCollection) { return ((IWrappedCollection)list).UnderlyingCollection; } value = list; } else { value = PopulateList(arrayContract.CreateWrapper(existingValue), reader, arrayContract, member, id); } } else { value = CreateJToken(reader, contract); } return value; }
private bool ReadSpecialProperties(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id) { id = null; newValue = null; if (reader.TokenType == JsonToken.PropertyName) { string propertyName = reader.Value.ToString(); if (propertyName.Length > 0 && propertyName[0] == '$') { // read 'special' properties // $type, $id, $ref, etc bool specialProperty; do { propertyName = reader.Value.ToString(); if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal)) { CheckedRead(reader); if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null) throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName)); string reference = (reader.Value != null) ? reader.Value.ToString() : null; CheckedRead(reader); if (reference != null) { if (reader.TokenType == JsonToken.PropertyName) throw JsonSerializationException.Create(reader, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName)); { newValue = Serializer.ReferenceResolver.ResolveReference(this, reference); return true; } } else { specialProperty = true; } } else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal)) { CheckedRead(reader); string qualifiedTypeName = reader.Value.ToString(); TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null) ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null) ?? ((containerMember != null) ? containerMember.ItemTypeNameHandling : null) ?? Serializer.TypeNameHandling; if (resolvedTypeNameHandling != TypeNameHandling.None) { string typeName; string assemblyName; ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName, out typeName, out assemblyName); Type specifiedType; try { specifiedType = Serializer.Binder.BindToType(assemblyName, typeName); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex); } if (specifiedType == null) throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); if (objectType != null #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) && objectType != typeof (IDynamicMetaObjectProvider) #endif && !objectType.IsAssignableFrom(specifiedType)) throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName)); objectType = specifiedType; contract = GetContractSafe(specifiedType); } CheckedRead(reader); specialProperty = true; } else if (string.Equals(propertyName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) { CheckedRead(reader); id = (reader.Value != null) ? reader.Value.ToString() : null; CheckedRead(reader); specialProperty = true; } else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal)) { CheckedRead(reader); object list = CreateList(reader, objectType, contract, member, existingValue, id); CheckedRead(reader); newValue = list; return true; } else { specialProperty = false; } } while (specialProperty && reader.TokenType == JsonToken.PropertyName); } } 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 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 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.UnderlyingType.IsSealed()) ? property.PropertyContract : GetContractSafe(memberValue); if (ShouldWriteProperty(memberValue, property)) { if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) { writer.WritePropertyName(property.PropertyName); 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 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; if (!arrayContract.IsMultidimensionalArray) { SerializeList(writer, arrayContract.CreateWrapper(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, 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); converter.WriteJson(writer, value, GetInternalSerializer()); _serializeStack.RemoveAt(_serializeStack.Count - 1); } }
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 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 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, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { OnSerializing(writer, contract, values.UnderlyingCollection); _serializeStack.Add(values.UnderlyingCollection); bool hasWrittenMetadataObject = WriteStartArray(writer, values.UnderlyingCollection, 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, 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, values.UnderlyingCollection); }
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 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; foreach (JsonProperty property in contract.Properties) { // 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; } writer.WritePropertyName(property.PropertyName); 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 (value.TryGetMember(memberName, out memberValue)) { try { JsonContract valueContract = GetContractSafe(memberValue); 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) { 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, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { OnSerializing(writer, contract, values.UnderlyingDictionary); _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, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth); } else { throw; } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, values.UnderlyingDictionary); }
private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract) { if (contract == null) throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType)); JsonArrayContract arrayContract = contract as JsonArrayContract; if (arrayContract == null) throw JsonSerializationException.Create(reader, @"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly. To fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. ".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract))); return arrayContract; }
private object EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType) { if (targetType == null) return value; Type valueType = ReflectionUtils.GetObjectType(value); // type of value and type of target don't match // attempt to convert value's type to target's type if (valueType != targetType) { if (value == null && contract.IsNullable) return null; try { if (contract.IsConvertable) { JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract; if (contract.IsEnum) { if (value is string) return Enum.Parse(contract.NonNullableUnderlyingType, value.ToString(), true); if (ConvertUtils.IsInteger(primitiveContract.TypeCode)) return Enum.ToObject(contract.NonNullableUnderlyingType, value); } #if !(PORTABLE || PORTABLE40 || NET35 || NET20) if (value is BigInteger) return ConvertUtils.FromBigInteger((BigInteger)value, contract.NonNullableUnderlyingType); #endif // this won't work when converting to a custom IConvertible return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture); } return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(value), targetType), ex); } } return value; }
private object EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType) { if (targetType == null) return value; Type valueType = ReflectionUtils.GetObjectType(value); // type of value and type of target don't match // attempt to convert value's type to target's type if (valueType != targetType) { try { if (value == null && contract.IsNullable) return null; if (contract.IsConvertable) { if (contract.NonNullableUnderlyingType.IsEnum()) { if (value is string) return Enum.Parse(contract.NonNullableUnderlyingType, value.ToString(), true); else if (ConvertUtils.IsInteger(value)) return Enum.ToObject(contract.NonNullableUnderlyingType, value); } return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture); } return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, FormatValueForPrint(value), targetType), ex); } } return 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) return true; JsonToken tokenType = reader.TokenType; if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); ObjectCreationHandling objectCreationHandling = property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling); if ((objectCreationHandling != ObjectCreationHandling.Replace) && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject) && property.Readable) { currentValue = property.ValueProvider.GetValue(target); gottenCurrentValue = true; if (currentValue != null) { propertyContract = GetContractSafe(currentValue.GetType()); useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType()); } } if (!property.Writable && !useExistingValue) 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 && tokenType == JsonToken.Null) 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) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && JsonTokenUtils.IsPrimitiveToken(tokenType) && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue())) return true; 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 static void TrySimplifyingJson(RavenJObject jObject, JsonContract contract) { var objectContract = contract as JsonObjectContract; if (objectContract == null) return; var deferredActions = new List<Action>(); foreach (var kvp in jObject) { var prop = kvp; if (prop.Value == null) continue; var obj = prop.Value as RavenJObject; if (obj == null) continue; var jsonProperty = objectContract.Properties.GetClosestMatchProperty(prop.Key); if (ShouldSimplifyJsonBasedOnType(obj.Value<string>("$type"), jsonProperty) == false) continue; if (obj.ContainsKey("$values") == false) { deferredActions.Add(() => obj.Remove("$type")); } else { deferredActions.Add(() => jObject[prop.Key] = obj["$values"]); } } foreach (var deferredAction in deferredActions) { deferredAction(); } foreach (var prop in jObject.Where(prop => prop.Value != null)) { switch (prop.Value.Type) { case JTokenType.Array: foreach (var item in ((RavenJArray)prop.Value)) { var ravenJObject = item as RavenJObject; if (ravenJObject != null) TrySimplifyingJson(ravenJObject, contract); } break; case JTokenType.Object: TrySimplifyingJson((RavenJObject)prop.Value, contract); break; } } }
private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object currentObject, string message) { try { throw JsonSerializationException.Create(reader, message); } catch (Exception ex) { if (IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex)) HandleError(reader, false, 0); else throw; } }
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 OnDeserializing(JsonReader reader, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); contract.InvokeOnDeserializing(value, Serializer.Context); }
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 bool ReadForType(JsonReader reader, JsonContract contract, bool hasConverter) { // don't read properties with converters as a specific value // the value might be a string which will then get converted which will error if read as date for example if (hasConverter) return reader.Read(); ReadType t = (contract != null) ? contract.InternalReadType : ReadType.Read; switch (t) { case ReadType.Read: do { if (!reader.Read()) return false; } while (reader.TokenType == JsonToken.Comment); return true; case ReadType.ReadAsInt32: reader.ReadAsInt32(); break; case ReadType.ReadAsDecimal: reader.ReadAsDecimal(); break; case ReadType.ReadAsBytes: reader.ReadAsBytes(); break; case ReadType.ReadAsString: reader.ReadAsString(); break; case ReadType.ReadAsDateTime: reader.ReadAsDateTime(); break; #if !NET20 case ReadType.ReadAsDateTimeOffset: reader.ReadAsDateTimeOffset(); break; #endif default: throw new ArgumentOutOfRangeException(); } return (reader.TokenType != JsonToken.None); }
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 JToken CreateJToken(JsonReader reader, JsonContract contract) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (contract != null && contract.UnderlyingType == typeof (JRaw)) { return JRaw.Create(reader); } else { JToken token; using (JTokenWriter writer = new JTokenWriter()) { writer.WriteToken(reader); token = writer.Token; } return token; } }
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 object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue) { if (contract != null && contract.ContractType == JsonContractType.Linq) return CreateJToken(reader, contract); do { switch (reader.TokenType) { // populate a typed object or generic dictionary/array // depending upon whether an objectType was supplied case JsonToken.StartObject: return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue); case JsonToken.StartArray: return CreateList(reader, objectType, contract, member, existingValue, null); case JsonToken.Integer: case JsonToken.Float: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.String: // convert empty string to null automatically for nullable types if (string.IsNullOrEmpty((string)reader.Value) && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable) return null; // string that needs to be returned as a byte array should be base 64 decoded if (objectType == typeof (byte[])) return Convert.FromBase64String((string) reader.Value); return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.StartConstructor: string constructorName = reader.Value.ToString(); return EnsureType(reader, constructorName, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Null: case JsonToken.Undefined: #if !(NETFX_CORE || PORTABLE) if (objectType == typeof (DBNull)) return DBNull.Value; #endif return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Raw: return new JRaw((string) reader.Value); case JsonToken.Comment: // ignore break; default: throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType); } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); }
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); } }
internal string GetExpectedDescription(JsonContract contract) { switch (contract.ContractType) { case JsonContractType.Object: case JsonContractType.Dictionary: #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) case JsonContractType.Serializable: #endif #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) case JsonContractType.Dynamic: #endif return @"JSON object (e.g. {""name"":""value""})"; case JsonContractType.Array: return @"JSON array (e.g. [1,2,3])"; case JsonContractType.Primitive: return @"JSON primitive value (e.g. string, number, boolean, null)"; case JsonContractType.String: return @"JSON string value"; default: throw new ArgumentOutOfRangeException(); } }
private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract, JsonProperty containerProperty) { JsonConverter converter = null; if (memberConverter != null) { // member attribute converter converter = memberConverter; } else if (containerProperty != null && containerProperty.ItemConverter != null) { converter = containerProperty.ItemConverter; } else if (containerContract != null && containerContract.ItemConverter != null) { converter = containerContract.ItemConverter; } else if (contract != null) { JsonConverter matchingConverter; if (contract.Converter != null) // class attribute converter converter = contract.Converter; else if ((matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null) // passed in converters converter = matchingConverter; else if (contract.InternalConverter != null) // internally specified converter converter = contract.InternalConverter; } return converter; }
private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue) { CheckedRead(reader); string id; object newValue; if (ReadSpecialProperties(reader, ref objectType, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id)) return newValue; if (!HasDefinedType(objectType)) return CreateJObject(reader); if (contract == null) throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType)); switch (contract.ContractType) { case JsonContractType.Object: bool createdFromNonDefaultConstructor = false; JsonObjectContract objectContract = (JsonObjectContract) contract; object targetObject; if (existingValue != null) targetObject = existingValue; else targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultConstructor); // don't populate if read from non-default constructor because the object has already been read if (createdFromNonDefaultConstructor) return targetObject; return PopulateObject(targetObject, reader, objectContract, member, id); case JsonContractType.Primitive: JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract) contract; // if the content is inside $value then read past it if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal)) { CheckedRead(reader); object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, null, existingValue); CheckedRead(reader); return value; } break; case JsonContractType.Dictionary: JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract; object targetDictionary; if (existingValue != null) targetDictionary = existingValue; else targetDictionary = CreateNewDictionary(reader, dictionaryContract); return PopulateDictionary(dictionaryContract.CreateWrapper(targetDictionary), reader, dictionaryContract, member, id); #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) case JsonContractType.Dynamic: JsonDynamicContract dynamicContract = (JsonDynamicContract) contract; return CreateDynamic(reader, dynamicContract, member, id); #endif #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) case JsonContractType.Serializable: JsonISerializableContract serializableContract = (JsonISerializableContract) contract; return CreateISerializable(reader, serializableContract, id); #endif } throw JsonSerializationException.Create(reader, @"Cannot deserialize the current JSON object (e.g. {{""name"":""value""}}) into type '{0}' because the type requires a {1} to deserialize correctly. To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. ".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract))); }
private string GetPropertyName(JsonWriter writer, DictionaryEntry entry, JsonContract contract, out bool escape) { object key = entry.Key; string propertyName; JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract; if (primitiveContract != null) { if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable) { escape = false; StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeString(sw, (DateTime)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return sw.ToString(); } #if !NET20 else if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffset || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffsetNullable) { escape = false; StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return sw.ToString(); } #endif else { escape = true; return Convert.ToString(key, CultureInfo.InvariantCulture); } } else if (TryConvertToString(key, key.GetType(), out propertyName)) { escape = true; return propertyName; } else { escape = true; return key.ToString(); } }
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); }