/// <summary> /// Writes the current <see cref="JsonReader"/> token. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param> public void WriteToken(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); int currentDepth; if (reader.TokenType == JsonToken.None) currentDepth = -1; else if (!IsStartToken(reader.TokenType)) currentDepth = reader.Depth + 1; else currentDepth = reader.Depth; do { switch (reader.TokenType) { case JsonToken.None: // read to next break; case JsonToken.StartObject: WriteStartObject(); break; case JsonToken.StartArray: WriteStartArray(); break; case JsonToken.StartConstructor: string constructorName = reader.Value.ToString(); // write a JValue date when the constructor is for a date if (string.Compare(constructorName, "Date", StringComparison.Ordinal) == 0) WriteConstructorDate(reader); else WriteStartConstructor(reader.Value.ToString()); break; case JsonToken.PropertyName: WritePropertyName(reader.Value.ToString()); break; case JsonToken.Comment: WriteComment(reader.Value.ToString()); break; case JsonToken.Integer: WriteValue((long)reader.Value); break; case JsonToken.Float: WriteValue((double)reader.Value); break; case JsonToken.String: WriteValue(reader.Value.ToString()); break; case JsonToken.Boolean: WriteValue((bool)reader.Value); break; case JsonToken.Null: WriteNull(); break; case JsonToken.Undefined: WriteUndefined(); break; case JsonToken.EndObject: WriteEndObject(); break; case JsonToken.EndArray: WriteEndArray(); break; case JsonToken.EndConstructor: WriteEndConstructor(); break; case JsonToken.Date: WriteValue((DateTime)reader.Value); break; case JsonToken.Raw: WriteRawValue((string)reader.Value); break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type."); } } while ( // stop if we have reached the end of the token being read currentDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0) && reader.Read()); }
private void WriteConstructorDate(JsonReader reader) { if (!reader.Read()) throw new Exception("Unexpected end while reading date constructor."); if (reader.TokenType != JsonToken.Integer) throw new Exception("Unexpected token while reading date constructor. Expected Integer, got " + reader.TokenType); long ticks = (long)reader.Value; DateTime date = JsonConvert.ConvertJavaScriptTicksToDateTime(ticks); if (!reader.Read()) throw new Exception("Unexpected end while reading date constructor."); if (reader.TokenType != JsonToken.EndConstructor) throw new Exception("Unexpected token while reading date constructor. Expected EndConstructor, got " + reader.TokenType); WriteValue(date); }
private object CreateObjectFromNonDefaultConstructor(Type objectType, JsonReader reader) { // object should have a single constructor ConstructorInfo c = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).SingleOrDefault(); if (c == null) throw new JsonSerializationException("Could not find a public constructor for type {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); // create a dictionary to put retrieved values into JsonMemberMappingCollection memberMappings = GetMemberMappings(objectType); IDictionary<JsonMemberMapping, object> mappingValues = memberMappings.ToDictionary(kv => kv, kv => (object)null); bool exit = false; while (!exit && reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string memberName = reader.Value.ToString(); if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); JsonMemberMapping memberMapping; // attempt exact case match first // then try match ignoring case if (memberMappings.TryGetClosestMatchMapping(memberName, out memberMapping)) { if (!memberMapping.Ignored) { Type memberType = ReflectionUtils.GetMemberUnderlyingType(memberMapping.Member); mappingValues[memberMapping] = CreateObject(reader, memberType, null, memberMapping.MemberConverter); } } else { if (_missingMemberHandling == MissingMemberHandling.Error) throw new JsonSerializationException("Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, objectType.Name)); reader.Skip(); } break; case JsonToken.EndObject: exit = true; break; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } IDictionary<ParameterInfo, object> constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null); IDictionary<JsonMemberMapping, object> remainingMappingValues = new Dictionary<JsonMemberMapping, object>(); foreach (KeyValuePair<JsonMemberMapping, object> mappingValue in mappingValues) { ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, mappingValue.Key.MappingName).Key; if (matchingConstructorParameter != null) constructorParameters[matchingConstructorParameter] = mappingValue.Value; else remainingMappingValues.Add(mappingValue); } object createdObject = ReflectionUtils.CreateInstance(objectType, constructorParameters.Values.ToArray()); // go through unused values and set the newly created object's properties foreach (KeyValuePair<JsonMemberMapping, object> remainingMappingValue in remainingMappingValues) { if (ShouldSetMappingValue(remainingMappingValue.Key, remainingMappingValue.Value)) ReflectionUtils.SetMemberValue(remainingMappingValue.Key.Member, createdObject, remainingMappingValue.Value); } return createdObject; }
private object PopulateObject(object newObject, JsonReader reader, Type objectType) { JsonMemberMappingCollection memberMappings = GetMemberMappings(objectType); Dictionary<string, bool> requiredMappings = memberMappings.Where(m => m.Required).ToDictionary(m => m.MappingName, m => false); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string memberName = reader.Value.ToString(); if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); if (reader.TokenType != JsonToken.Null) SetRequiredMapping(memberName, requiredMappings); SetObjectMember(reader, newObject, objectType, memberName); break; case JsonToken.EndObject: foreach (KeyValuePair<string, bool> requiredMapping in requiredMappings) { if (!requiredMapping.Value) throw new JsonSerializationException("Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, requiredMapping.Key)); } return newObject; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } throw new JsonSerializationException("Unexpected end when deserializing object."); }
private IList PopulateList(IList list, Type listItemType, JsonReader reader) { while (reader.Read()) { switch (reader.TokenType) { case JsonToken.EndArray: return list; case JsonToken.Comment: break; default: object value = CreateObject(reader, listItemType, null, null); list.Add(value); break; } } throw new JsonSerializationException("Unexpected end when deserializing array."); }
private object CreateAndPopulateObject(JsonReader reader, Type objectType) { object newObject; if (objectType.IsInterface || objectType.IsAbstract) throw new JsonSerializationException("Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, objectType)); if (ReflectionUtils.HasDefaultConstructor(objectType)) { newObject = Activator.CreateInstance(objectType); PopulateObject(newObject, reader, objectType); return newObject; } return CreateObjectFromNonDefaultConstructor(objectType, reader); }
private IDictionary PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader) { Type dictionaryType = dictionary.UnderlyingDictionary.GetType(); Type dictionaryKeyType = ReflectionUtils.GetDictionaryKeyType(dictionaryType); Type dictionaryValueType = ReflectionUtils.GetDictionaryValueType(dictionaryType); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: object keyValue = EnsureType(reader.Value, dictionaryKeyType); reader.Read(); dictionary.Add(keyValue, CreateObject(reader, dictionaryValueType, null, null)); break; case JsonToken.EndObject: return dictionary; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } throw new JsonSerializationException("Unexpected end when deserializing object."); }
/// <summary> /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/> /// into an instance of the specified type. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> containing the object.</param> /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param> /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns> public object Deserialize(JsonReader reader, Type objectType) { if (reader == null) throw new ArgumentNullException("reader"); if (!reader.Read()) return null; if (objectType != null) return CreateObject(reader, objectType, null, null); else return CreateJToken(reader); }
private void SetMappingValue(JsonMemberMapping memberMapping, JsonReader reader, object target) { if (memberMapping.Ignored) { reader.Skip(); return; } // get the member's underlying type Type memberType = ReflectionUtils.GetMemberUnderlyingType(memberMapping.Member); object currentValue = null; bool useExistingValue = false; if ((_objectCreationHandling == ObjectCreationHandling.Auto || _objectCreationHandling == ObjectCreationHandling.Reuse) && (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)) { currentValue = ReflectionUtils.GetMemberValue(memberMapping.Member, target); useExistingValue = (currentValue != null && !memberType.IsArray && !ReflectionUtils.InheritsGenericDefinition(memberType, typeof(ReadOnlyCollection<>))); } if (!memberMapping.Writable && !useExistingValue) { reader.Skip(); return; } object value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null, JsonTypeReflector.GetConverter(memberMapping.Member, memberType)); if (!useExistingValue && ShouldSetMappingValue(memberMapping, value)) ReflectionUtils.SetMemberValue(memberMapping.Member, target, value); }
private object CreateAndPopulateDictionary(JsonReader reader, Type objectType) { if (IsTypeGenericDictionaryInterface(objectType)) { Type keyType; Type valueType; ReflectionUtils.GetDictionaryKeyValueTypes(objectType, out keyType, out valueType); objectType = ReflectionUtils.MakeGenericType(typeof(Dictionary<,>), keyType, valueType); } IWrappedDictionary dictionary = CollectionUtils.CreateDictionaryWrapper(Activator.CreateInstance(objectType)); PopulateDictionary(dictionary, reader); return dictionary.UnderlyingDictionary; }
private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName) { JsonMemberMappingCollection memberMappings = GetMemberMappings(targetType); JsonMemberMapping memberMapping; // attempt exact case match first // then try match ignoring case if (memberMappings.TryGetClosestMatchMapping(memberName, out memberMapping)) { SetMappingValue(memberMapping, reader, target); } else { if (_missingMemberHandling == MissingMemberHandling.Error) throw new JsonSerializationException("Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, targetType.Name)); reader.Skip(); } }
private object CreateObject(JsonReader reader, Type objectType, object existingValue, JsonConverter memberConverter) { _level++; object value; JsonConverter converter; if (memberConverter != null) { return memberConverter.ReadJson(reader, objectType); } else if (objectType != null && HasClassConverter(objectType, out converter)) { return converter.ReadJson(reader, objectType); } else if (objectType != null && HasMatchingConverter(objectType, out converter)) { return converter.ReadJson(reader, objectType); } else if (objectType == typeof(JsonRaw)) { return JsonRaw.Create(reader); } else { switch (reader.TokenType) { // populate a typed object or generic dictionary/array // depending upon whether an objectType was supplied case JsonToken.StartObject: if (objectType == null) { value = CreateJToken(reader); } else if (CollectionUtils.IsDictionaryType(objectType)) { if (existingValue == null) value = CreateAndPopulateDictionary(reader, objectType); else value = PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(existingValue), reader); } else { if (existingValue == null) value = CreateAndPopulateObject(reader, objectType); else value = PopulateObject(existingValue, reader, objectType); } break; case JsonToken.StartArray: if (objectType != null) { if (existingValue == null) value = CreateAndPopulateList(reader, objectType); else value = PopulateList(CollectionUtils.CreateCollectionWrapper(existingValue), ReflectionUtils.GetCollectionItemType(objectType), reader); } else { value = CreateJToken(reader); } break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: value = EnsureType(reader.Value, objectType); break; case JsonToken.StartConstructor: case JsonToken.EndConstructor: string constructorName = reader.Value.ToString(); value = constructorName; break; case JsonToken.Null: case JsonToken.Undefined: if (objectType == typeof(DBNull)) value = DBNull.Value; else value = null; break; default: throw new JsonSerializationException("Unexpected token while deserializing object: " + reader.TokenType); } } _level--; return value; }
private JToken CreateJToken(JsonReader reader) { JToken token; using (JsonTokenWriter writer = new JsonTokenWriter()) { writer.WriteToken(reader); token = writer.Token; } return token; }
/// <summary> /// Reads the JSON representation of the object. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> /// <param name="objectType">Type of the object.</param> /// <returns>The object value.</returns> public abstract object ReadJson(JsonReader reader, Type objectType);
private object CreateAndPopulateList(JsonReader reader, Type objectType) { if (IsTypeGenericCollectionInterface(objectType)) { Type itemType = ReflectionUtils.GetCollectionItemType(objectType); objectType = ReflectionUtils.MakeGenericType(typeof(List<>), itemType); } return CollectionUtils.CreateAndPopulateList(objectType, l => PopulateList(l, ReflectionUtils.GetCollectionItemType(objectType), reader)); }
/// <summary> /// Creates an instance of <see cref="JsonRaw"/> with the content of the reader's current token. /// </summary> /// <param name="reader">The reader.</param> /// <returns>An instance of <see cref="JsonRaw"/> with the content of the reader's current token.</returns> public static JsonRaw Create(JsonReader reader) { using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) using (JsonTextWriter jsonWriter = new JsonTextWriter(sw)) { jsonWriter.WriteToken(reader); return new JsonRaw(sw.ToString()); } }
/// <summary> /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> that contains the Json structure to deserialize.</param> /// <returns>The <see cref="Object"/> being deserialized.</returns> public object Deserialize(JsonReader reader) { return Deserialize(reader, null); }