diff --git a/Src/Newtonsoft.Json.Silverlight/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json.Silverlight/Newtonsoft.Json.Silverlight.csproj index 0e2e7b4e..f407d9df 100644 --- a/Src/Newtonsoft.Json.Silverlight/Newtonsoft.Json.Silverlight.csproj +++ b/Src/Newtonsoft.Json.Silverlight/Newtonsoft.Json.Silverlight.csproj @@ -70,6 +70,9 @@ JsonConverter.cs + + JsonConverterAttribute.cs + JsonConverterCollection.cs diff --git a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs index 80cb943f..15aacda4 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs @@ -54,6 +54,24 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual(@"""2000-12-15T22:11:03.0550000" + d.GetLocalOffset() + @"""", result); } + [Test] + public void SerializeFormattedDateTime() + { + IsoDateTimeConverter converter = new IsoDateTimeConverter() { DateTimeFormat = "F" }; + + DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 0, DateTimeKind.Utc); + string result; + + result = JavaScriptConvert.SerializeObject(d, converter); + Assert.AreEqual(@"""Friday, 15 December 2000 22:11:03""", result); + + Assert.AreEqual(d, JavaScriptConvert.DeserializeObject(result, converter)); + + d = new DateTime(2000, 12, 15, 22, 11, 3, 0, DateTimeKind.Local); + result = JavaScriptConvert.SerializeObject(d, converter); + Assert.AreEqual(@"""Friday, 15 December 2000 22:11:03""", result); + } + [Test] public void SerializeDateTimeOffset() { diff --git a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs index 51211b00..4c8377e3 100644 --- a/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonSerializerTest.cs @@ -37,6 +37,8 @@ using Newtonsoft.Json.Linq; using System.Linq; using Newtonsoft.Json.Converters; using System.Runtime.Serialization.Json; +using Newtonsoft.Json.Utilities; +using System.Globalization; namespace Newtonsoft.Json.Tests { @@ -1097,5 +1099,170 @@ keyword such as type of business."" Assert.AreEqual("Param1", deserialized.Param1); Assert.AreEqual("Param2", deserialized.Param2); } + + public class MemberConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter + { + public override string ConverterType + { + get { return "Member"; } + } + } + + public class ClassConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter + { + public override string ConverterType + { + get { return "Class"; } + } + } + + public class ArgumentConverterPrecedenceClassConverter : ConverterPrecedenceClassConverter + { + public override string ConverterType + { + get { return "Argument"; } + } + } + + public abstract class ConverterPrecedenceClassConverter : JsonConverter + { + public abstract string ConverterType { get; } + + public override void WriteJson(JsonWriter writer, object value) + { + ConverterPrecedenceClass c = (ConverterPrecedenceClass)value; + + JToken j = new JArray(ConverterType, c.TestValue); + + j.WriteTo(writer); + } + + public override object ReadJson(JsonReader reader, Type objectType) + { + JToken j = JArray.Load(reader); + + string converter = (string)j[0]; + if (converter != ConverterType) + throw new Exception("Serialize converter {0} and deserialize converter {1} do not match.".FormatWith(CultureInfo.InvariantCulture, converter, ConverterType)); + + string testValue = (string)j[1]; + return new ConverterPrecedenceClass(testValue); + } + + public override bool CanConvert(Type objectType) + { + return (objectType == typeof(ConverterPrecedenceClass)); + } + } + + [JsonConverter(typeof(ClassConverterPrecedenceClassConverter))] + public class ConverterPrecedenceClass + { + public string TestValue { get; set; } + + public ConverterPrecedenceClass(string testValue) + { + TestValue = testValue; + } + } + + [Test] + public void SerializerShouldUseClassConverter() + { + ConverterPrecedenceClass c1 = new ConverterPrecedenceClass("!Test!"); + + string json = JavaScriptConvert.SerializeObject(c1); + Assert.AreEqual(@"[""Class"",""!Test!""]", json); + + ConverterPrecedenceClass c2 = JavaScriptConvert.DeserializeObject(json); + + Assert.AreEqual("!Test!", c2.TestValue); + } + + [Test] + public void SerializerShouldUseClassConverterOverArgumentConverter() + { + ConverterPrecedenceClass c1 = new ConverterPrecedenceClass("!Test!"); + + string json = JavaScriptConvert.SerializeObject(c1, new ArgumentConverterPrecedenceClassConverter()); + Assert.AreEqual(@"[""Class"",""!Test!""]", json); + + ConverterPrecedenceClass c2 = JavaScriptConvert.DeserializeObject(json, new ArgumentConverterPrecedenceClassConverter()); + + Assert.AreEqual("!Test!", c2.TestValue); + } + + public class MemberConverterClass + { + public DateTime DefaultConverter { get; set; } + [JsonConverter(typeof(IsoDateTimeConverter))] + public DateTime MemberConverter { get; set; } + } + + [Test] + public void SerializerShouldUseMemberConverter() + { + DateTime testDate = new DateTime(JavaScriptConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); + MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate }; + + string json = JavaScriptConvert.SerializeObject(m1); + Assert.AreEqual(@"{""DefaultConverter"":""\/Date(0)\/"",""MemberConverter"":""1970-01-01T00:00:00.0000000Z""}", json); + + MemberConverterClass m2 = JavaScriptConvert.DeserializeObject(json); + + Assert.AreEqual(testDate, m2.DefaultConverter); + Assert.AreEqual(testDate, m2.MemberConverter); + } + + [Test] + public void SerializerShouldUseMemberConverterOverArgumentConverter() + { + DateTime testDate = new DateTime(JavaScriptConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); + MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate }; + + string json = JavaScriptConvert.SerializeObject(m1, new JavaScriptDateTimeConverter()); + Assert.AreEqual(@"{""DefaultConverter"":new Date(0),""MemberConverter"":""1970-01-01T00:00:00.0000000Z""}", json); + + MemberConverterClass m2 = JavaScriptConvert.DeserializeObject(json, new JavaScriptDateTimeConverter()); + + Assert.AreEqual(testDate, m2.DefaultConverter); + Assert.AreEqual(testDate, m2.MemberConverter); + } + + public class ClassAndMemberConverterClass + { + public ConverterPrecedenceClass DefaultConverter { get; set; } + [JsonConverter(typeof(MemberConverterPrecedenceClassConverter))] + public ConverterPrecedenceClass MemberConverter { get; set; } + } + + [Test] + public void SerializerShouldUseMemberConverterOverClassAndArgumentConverter() + { + ClassAndMemberConverterClass c1 = new ClassAndMemberConverterClass(); + c1.DefaultConverter = new ConverterPrecedenceClass("DefaultConverterValue"); + c1.MemberConverter = new ConverterPrecedenceClass("MemberConverterValue"); + + string json = JavaScriptConvert.SerializeObject(c1, new ArgumentConverterPrecedenceClassConverter()); + Assert.AreEqual(@"{""DefaultConverter"":[""Class"",""DefaultConverterValue""],""MemberConverter"":[""Member"",""MemberConverterValue""]}", json); + + ClassAndMemberConverterClass c2 = JavaScriptConvert.DeserializeObject(json, new ArgumentConverterPrecedenceClassConverter()); + + Assert.AreEqual("DefaultConverterValue", c2.DefaultConverter.TestValue); + Assert.AreEqual("MemberConverterValue", c2.MemberConverter.TestValue); + } + + [JsonConverter(typeof(IsoDateTimeConverter))] + public class IncompatibleJsonAttributeClass + { + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "JsonConverter IsoDateTimeConverter on Newtonsoft.Json.Tests.JsonSerializerTest+IncompatibleJsonAttributeClass is not compatible with member type IncompatibleJsonAttributeClass.")] + public void IncompatibleJsonAttributeShouldThrow() + { + IncompatibleJsonAttributeClass c = new IncompatibleJsonAttributeClass(); + JavaScriptConvert.SerializeObject(c); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs index 25359f48..6e3c7eee 100644 --- a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs @@ -12,9 +12,10 @@ namespace Newtonsoft.Json.Converters /// public class IsoDateTimeConverter : JsonConverter { - private const string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; + private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; + private string _dateTimeFormat = DefaultDateTimeFormat; /// /// Gets or sets the date time styles used when converting a date to and from JSON. @@ -26,6 +27,16 @@ namespace Newtonsoft.Json.Converters set { _dateTimeStyles = value; } } + /// + /// Gets or sets the date time format used when converting a date to and fromm JSON. + /// + /// The date time format used when converting a date to and from JSON. + public string DateTimeFormat + { + get { return _dateTimeFormat; } + set { _dateTimeFormat = value; } + } + /// /// Writes the JSON representation of the object. /// @@ -43,7 +54,7 @@ namespace Newtonsoft.Json.Converters || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) dateTime = dateTime.ToUniversalTime(); - text = dateTime.ToString(DateTimeFormat, CultureInfo.InvariantCulture); + text = dateTime.ToString(_dateTimeFormat, CultureInfo.InvariantCulture); } else { @@ -52,7 +63,7 @@ namespace Newtonsoft.Json.Converters || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) dateTimeOffset = dateTimeOffset.ToUniversalTime(); - text = dateTimeOffset.ToString(DateTimeFormat, CultureInfo.InvariantCulture); + text = dateTimeOffset.ToString(_dateTimeFormat, CultureInfo.InvariantCulture); } writer.WriteValue(text); diff --git a/Src/Newtonsoft.Json/JsonConverterAttribute.cs b/Src/Newtonsoft.Json/JsonConverterAttribute.cs new file mode 100644 index 00000000..94998cb3 --- /dev/null +++ b/Src/Newtonsoft.Json/JsonConverterAttribute.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Newtonsoft.Json.Utilities; +using System.Globalization; + +namespace Newtonsoft.Json +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false)] + public class JsonConverterAttribute : Attribute + { + private readonly Type _converterType; + + public Type ConverterType + { + get { return _converterType; } + } + + public JsonConverterAttribute(Type converterType) + { + if (converterType == null) + throw new ArgumentNullException("converterType"); + + _converterType = converterType; + } + + internal JsonConverter CreateJsonConverterInstance() + { + try + { + return (JsonConverter)Activator.CreateInstance(_converterType); + } + catch (Exception ex) + { + throw new Exception("Error creating {0}".FormatWith(CultureInfo.InvariantCulture, _converterType), ex); + } + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index 7f7640be..516944a2 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -166,7 +166,7 @@ namespace Newtonsoft.Json return null; if (objectType != null) - return CreateObject(reader, objectType, null); + return CreateObject(reader, objectType, null, null); else return CreateJToken(reader); } @@ -195,14 +195,31 @@ namespace Newtonsoft.Json return token; } - private object CreateObject(JsonReader reader, Type objectType, object existingValue) + private bool HasClassConverter(Type objectType, out JsonConverter converter) + { + if (objectType == null) + throw new ArgumentNullException("objectType"); + + converter = GetConverter(objectType, objectType); + return (converter != null); + } + + private object CreateObject(JsonReader reader, Type objectType, object existingValue, JsonConverter memberConverter) { _level++; object value; JsonConverter converter; - if (HasMatchingConverter(objectType, out 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); } @@ -338,7 +355,10 @@ namespace Newtonsoft.Json bool readable = ReflectionUtils.CanReadMemberValue(member); bool writable = ReflectionUtils.CanSetMemberValue(member); - MemberMapping memberMapping = new MemberMapping(mappedName, member, ignored, readable, writable); + + JsonConverter memberConverter = GetConverter(member, ReflectionUtils.GetMemberUnderlyingType(member)); + + MemberMapping memberMapping = new MemberMapping(mappedName, member, ignored, readable, writable, memberConverter); memberMappings.AddMapping(memberMapping); } @@ -366,6 +386,23 @@ namespace Newtonsoft.Json return objectAttribute.MemberSerialization; } + private JsonConverter GetConverter(ICustomAttributeProvider attributeProvider, Type targetConvertedType) + { + JsonConverterAttribute converterAttribute = ReflectionUtils.GetAttribute(attributeProvider, true); + + if (converterAttribute != null) + { + JsonConverter memberConverter = converterAttribute.CreateJsonConverterInstance(); + + if (!memberConverter.CanConvert(targetConvertedType)) + throw new JsonSerializationException("JsonConverter {0} on {1} is not compatible with member type {2}.".FormatWith(CultureInfo.InvariantCulture, memberConverter.GetType().Name, attributeProvider, targetConvertedType.Name)); + + return memberConverter; + } + + return null; + } + private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName) { if (!reader.Read()) @@ -402,7 +439,7 @@ namespace Newtonsoft.Json return; } - value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null); + value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null, GetConverter(memberMapping.Member, memberType)); if (_nullValueHandling == NullValueHandling.Ignore && value == null) return; @@ -439,7 +476,7 @@ namespace Newtonsoft.Json object keyValue = EnsureType(reader.Value, dictionaryKeyType); reader.Read(); - dictionary.Add(keyValue, CreateObject(reader, dictionaryValueType, null)); + dictionary.Add(keyValue, CreateObject(reader, dictionaryValueType, null, null)); break; case JsonToken.EndObject: return dictionary; @@ -467,7 +504,7 @@ namespace Newtonsoft.Json case JsonToken.Comment: break; default: - object value = CreateObject(reader, listItemType, null); + object value = CreateObject(reader, listItemType, null, null); list.Add(value); break; @@ -497,6 +534,7 @@ namespace Newtonsoft.Json // create a dictionary to put retrieved values into IDictionary constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null); + MemberMappingCollection mappings = GetMemberMappings(objectType); bool exit = false; while (!exit && reader.Read()) @@ -505,16 +543,21 @@ namespace Newtonsoft.Json { case JsonToken.PropertyName: string memberName = reader.Value.ToString(); - ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, memberName).Key; - if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - if (matchingConstructorParameter != null) - constructorParameters[matchingConstructorParameter] = CreateObject(reader, matchingConstructorParameter.ParameterType, null); - else - reader.Skip(); + ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, memberName).Key; + MemberMapping mapping; + if (matchingConstructorParameter != null && mappings.TryGetMapping(memberName, out mapping) && !mapping.Ignored) + { + constructorParameters[matchingConstructorParameter] = CreateObject(reader, matchingConstructorParameter.ParameterType, null, mapping.MemberConverter); + } + else + { + // skip token and all child tokens + reader.Skip(); + } break; case JsonToken.EndObject: exit = true; @@ -578,11 +621,11 @@ namespace Newtonsoft.Json if (value is JToken) ((JToken)value).WriteTo(jsonWriter, (_converters != null) ? _converters.ToArray() : null); else - SerializeValue(jsonWriter, value); + SerializeValue(jsonWriter, value, null); } - private void SerializeValue(JsonWriter writer, object value) + private void SerializeValue(JsonWriter writer, object value, JsonConverter memberConverter) { JsonConverter converter; @@ -590,6 +633,14 @@ namespace Newtonsoft.Json { writer.WriteNull(); } + else if (memberConverter != null) + { + memberConverter.WriteJson(writer, value); + } + else if (HasClassConverter(value.GetType(), out converter)) + { + converter.WriteJson(writer, value); + } else if (HasMatchingConverter(value.GetType(), out converter)) { converter.WriteJson(writer, value); @@ -601,49 +652,49 @@ namespace Newtonsoft.Json switch (convertible.GetTypeCode()) { case TypeCode.String: - writer.WriteValue((string)convertible); + writer.WriteValue(convertible.ToString(CultureInfo.InvariantCulture)); break; case TypeCode.Char: - writer.WriteValue((char)convertible); + writer.WriteValue(convertible.ToChar(CultureInfo.InvariantCulture)); break; case TypeCode.Boolean: - writer.WriteValue((bool)convertible); + writer.WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture)); break; case TypeCode.SByte: - writer.WriteValue((sbyte)convertible); + writer.WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture)); break; case TypeCode.Int16: - writer.WriteValue((short)convertible); + writer.WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture)); break; case TypeCode.UInt16: - writer.WriteValue((ushort)convertible); + writer.WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture)); break; case TypeCode.Int32: - writer.WriteValue((int)convertible); + writer.WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture)); break; case TypeCode.Byte: - writer.WriteValue((byte)convertible); + writer.WriteValue(convertible.ToByte(CultureInfo.InvariantCulture)); break; case TypeCode.UInt32: - writer.WriteValue((uint)convertible); + writer.WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture)); break; case TypeCode.Int64: - writer.WriteValue((long)convertible); + writer.WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture)); break; case TypeCode.UInt64: - writer.WriteValue((ulong)convertible); + writer.WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture)); break; case TypeCode.Single: - writer.WriteValue((float)convertible); + writer.WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture)); break; case TypeCode.Double: - writer.WriteValue((double)convertible); + writer.WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture)); break; case TypeCode.DateTime: - writer.WriteValue((DateTime)convertible); + writer.WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture)); break; case TypeCode.Decimal: - writer.WriteValue((decimal)convertible); + writer.WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture)); break; case TypeCode.DBNull: writer.WriteNull(); @@ -688,15 +739,18 @@ namespace Newtonsoft.Json return HasMatchingConverter(_converters, type, out matchingConverter); } - internal static bool HasMatchingConverter(IList converters, Type type, out JsonConverter matchingConverter) + internal static bool HasMatchingConverter(IList converters, Type objectType, out JsonConverter matchingConverter) { + if (objectType == null) + throw new ArgumentNullException("objectType"); + if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter converter = converters[i]; - if (converter.CanConvert(type)) + if (converter.CanConvert(objectType)) { matchingConverter = converter; return true; @@ -708,7 +762,7 @@ namespace Newtonsoft.Json return false; } - private void WriteMemberInfoProperty(JsonWriter writer, object value, MemberInfo member, string propertyName) + private void WriteMemberInfoProperty(JsonWriter writer, object value, MemberInfo member, string propertyName, JsonConverter memberConverter) { if (!ReflectionUtils.IsIndexedProperty(member)) { @@ -735,7 +789,7 @@ namespace Newtonsoft.Json } writer.WritePropertyName(propertyName ?? member.Name); - SerializeValue(writer, memberValue); + SerializeValue(writer, memberValue, memberConverter); } } @@ -772,7 +826,7 @@ namespace Newtonsoft.Json foreach (MemberMapping memberMapping in memberMappings) { if (!memberMapping.Ignored && memberMapping.Readable) - WriteMemberInfoProperty(writer, value, memberMapping.Member, memberMapping.MappingName); + WriteMemberInfoProperty(writer, value, memberMapping.Member, memberMapping.MappingName, memberMapping.MemberConverter); } writer.WriteEndObject(); @@ -796,7 +850,7 @@ namespace Newtonsoft.Json for (int i = 0; i < values.Count; i++) { - SerializeValue(writer, values[i]); + SerializeValue(writer, values[i], null); } writer.WriteEndArray(); @@ -809,7 +863,7 @@ namespace Newtonsoft.Json foreach (DictionaryEntry entry in values) { writer.WritePropertyName(entry.Key.ToString()); - SerializeValue(writer, entry.Value); + SerializeValue(writer, entry.Value, null); } writer.WriteEndObject(); diff --git a/Src/Newtonsoft.Json/MemberMapping.cs b/Src/Newtonsoft.Json/MemberMapping.cs index 50ae699c..8f65601b 100644 --- a/Src/Newtonsoft.Json/MemberMapping.cs +++ b/Src/Newtonsoft.Json/MemberMapping.cs @@ -37,14 +37,16 @@ namespace Newtonsoft.Json private readonly bool _ignored; private readonly bool _readable; private readonly bool _writable; + private readonly JsonConverter _memberConverter; - public MemberMapping(string mappingName, MemberInfo member, bool ignored, bool readable, bool writable) + public MemberMapping(string mappingName, MemberInfo member, bool ignored, bool readable, bool writable, JsonConverter memberConverter) { _mappingName = mappingName; _member = member; _ignored = ignored; _readable = readable; _writable = writable; + _memberConverter = memberConverter; } public string MappingName @@ -71,5 +73,10 @@ namespace Newtonsoft.Json { get { return _writable; } } + + public JsonConverter MemberConverter + { + get { return _memberConverter; } + } } } diff --git a/Src/Newtonsoft.Json/MemberMappingCollection.cs b/Src/Newtonsoft.Json/MemberMappingCollection.cs index 807fb0ff..2f0b0ef4 100644 --- a/Src/Newtonsoft.Json/MemberMappingCollection.cs +++ b/Src/Newtonsoft.Json/MemberMappingCollection.cs @@ -63,5 +63,19 @@ namespace Newtonsoft.Json Add(memberMapping); } + + public bool TryGetMapping(string mappingName, out MemberMapping memberMapping) + { + if (Contains(mappingName)) + { + memberMapping = this[mappingName]; + return true; + } + else + { + memberMapping = default(MemberMapping); + return false; + } + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index 3204f74e..9ef8ca05 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -74,6 +74,7 @@ +