Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/Newtonsoft.Json.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
authorJamesNK <james@newtonking.com>2010-03-23 03:21:57 +0300
committerJamesNK <james@newtonking.com>2010-03-23 03:21:57 +0300
commit7f7cccd598038f9e51d8b121f04373702cd1d7eb (patch)
tree4c70ee7b4478483fcacd065b61a00be212eee7cf /Src
parent408a407105b5cee654caebc0ef2d80f29f2f6990 (diff)
-Add support for using implicit/explicit casts when converting a JSON property name to a dictionary value
-Fix DynamicReflectionDelegateFactory erroring when calling static methods -Fix CustomCreationConverter to return null when converting a null JSON value
Diffstat (limited to 'Src')
-rw-r--r--Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs81
-rw-r--r--Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs38
-rw-r--r--Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs18
-rw-r--r--Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs3
-rw-r--r--Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs2
-rw-r--r--Src/Newtonsoft.Json/Utilities/ConvertUtils.cs78
-rw-r--r--Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs2
7 files changed, 214 insertions, 8 deletions
diff --git a/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs
index f50f085..43a1502 100644
--- a/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Converters/CustomCreationConverterTests.cs
@@ -145,5 +145,86 @@ namespace Newtonsoft.Json.Tests.Converters
const string expected = @"{""Value"":""Foo"",""Thing"":{""Number"":456}}";
Assert.AreEqual(expected, json);
}
+
+ internal interface IRange<T>
+ {
+ T First { get; }
+ T Last { get; }
+ }
+
+ internal class Range<T> : IRange<T>
+ {
+ public T First { get; set; }
+ public T Last { get; set; }
+ }
+
+ internal class NullInterfaceTestClass
+ {
+ public virtual Guid Id { get; set; }
+ public virtual int? Year { get; set; }
+ public virtual string Company { get; set; }
+ public virtual IRange<decimal> DecimalRange { get; set; }
+ public virtual IRange<int> IntRange { get; set; }
+ public virtual IRange<decimal> NullDecimalRange { get; set; }
+ }
+
+ internal class DecimalRangeConverter : CustomCreationConverter<IRange<decimal>>
+ {
+ public override IRange<decimal> Create(Type objectType)
+ {
+ return new Range<decimal>();
+ }
+ }
+
+ internal class IntRangeConverter : CustomCreationConverter<IRange<int>>
+ {
+ public override IRange<int> Create(Type objectType)
+ {
+ return new Range<int>();
+ }
+ }
+
+ [Test]
+ public void DeserializeAndConvertNullValue()
+ {
+ NullInterfaceTestClass initial = new NullInterfaceTestClass
+ {
+ Company = "Company!",
+ DecimalRange = new Range<decimal> { First = 0, Last = 1 },
+ Id = new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
+ IntRange = new Range<int> { First = int.MinValue, Last = int.MaxValue },
+ Year = 2010,
+ NullDecimalRange = null
+ };
+
+ string json = JsonConvert.SerializeObject(initial, Formatting.Indented);
+
+ Assert.AreEqual(@"{
+ ""Id"": ""00000001-0002-0003-0405-060708090a0b"",
+ ""Year"": 2010,
+ ""Company"": ""Company!"",
+ ""DecimalRange"": {
+ ""First"": 0.0,
+ ""Last"": 1.0
+ },
+ ""IntRange"": {
+ ""First"": -2147483648,
+ ""Last"": 2147483647
+ },
+ ""NullDecimalRange"": null
+}", json);
+
+ NullInterfaceTestClass deserialized = JsonConvert.DeserializeObject<NullInterfaceTestClass>(
+ json, new IntRangeConverter(), new DecimalRangeConverter());
+
+ Assert.AreEqual("Company!", deserialized.Company);
+ Assert.AreEqual(new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), deserialized.Id);
+ Assert.AreEqual(0, deserialized.DecimalRange.First);
+ Assert.AreEqual(1, deserialized.DecimalRange.Last);
+ Assert.AreEqual(int.MinValue, deserialized.IntRange.First);
+ Assert.AreEqual(int.MaxValue, deserialized.IntRange.Last);
+ Assert.AreEqual(null, deserialized.NullDecimalRange);
+ Assert.AreEqual(2010, deserialized.Year);
+ }
}
} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
index a2362ab..0ace842 100644
--- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
+++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs
@@ -2000,7 +2000,7 @@ keyword such as type of business.""
}
[Test]
- [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Could not convert string 'Newtonsoft.Json.Tests.TestObjects.Person' to dictionary key type Newtonsoft.Json.Tests.TestObjects.Person. Create a TypeConverter to convert from the string to the key type object.")]
+ [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Could not convert string 'Newtonsoft.Json.Tests.TestObjects.Person' to dictionary key type 'Newtonsoft.Json.Tests.TestObjects.Person'. Create a TypeConverter to convert from the string to the key type object.")]
public void DeserializePersonKeyedDictionary()
{
string json =
@@ -3316,5 +3316,41 @@ keyword such as type of business.""
Assert.AreEqual("James", deserialized.Name);
Assert.AreEqual(27, deserialized.Age);
}
+
+ public class DictionaryKey
+ {
+ public string Value { get; set; }
+
+ public override string ToString()
+ {
+ return Value;
+ }
+
+ public static implicit operator DictionaryKey(string value)
+ {
+ return new DictionaryKey() {Value = value};
+ }
+ }
+
+ [Test]
+ public void SerializeDeserializeDictionaryKey()
+ {
+ Dictionary<DictionaryKey, string> dictionary = new Dictionary<DictionaryKey, string>();
+
+ dictionary.Add(new DictionaryKey() { Value = "First!" }, "First");
+ dictionary.Add(new DictionaryKey() { Value = "Second!" }, "Second");
+
+ string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented);
+
+ Assert.AreEqual(@"{
+ ""First!"": ""First"",
+ ""Second!"": ""Second""
+}", json);
+
+ Dictionary<DictionaryKey, string> newDictionary =
+ JsonConvert.DeserializeObject<Dictionary<DictionaryKey, string>>(json);
+
+ Assert.AreEqual(2, newDictionary.Count);
+ }
}
} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs b/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs
index bbe80e0..c8123fe 100644
--- a/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs
@@ -27,10 +27,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Utilities;
using Newtonsoft.Json.Tests.TestObjects;
+using Newtonsoft.Json.Tests.Serialization;
namespace Newtonsoft.Json.Tests.Utilities
{
@@ -89,6 +91,22 @@ namespace Newtonsoft.Json.Tests.Utilities
setter(m, new Version());
}
+
+ [Test]
+ public void CreateStaticMethodCall()
+ {
+ MethodInfo castMethodInfo = typeof(JsonSerializerTest.DictionaryKey).GetMethod("op_Implicit", new[] { typeof(string) });
+
+ Assert.IsNotNull(castMethodInfo);
+
+ MethodCall<object, object> call = DynamicReflectionDelegateFactory.Instance.CreateMethodCall<object>(castMethodInfo);
+
+ object result = call(null, "First!");
+ Assert.IsNotNull(result);
+
+ JsonSerializerTest.DictionaryKey key = (JsonSerializerTest.DictionaryKey) result;
+ Assert.AreEqual("First!", key.Value);
+ }
}
}
#endif \ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs
index ecd8e61..a7eb499 100644
--- a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs
+++ b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs
@@ -54,6 +54,9 @@ namespace Newtonsoft.Json.Converters
/// <returns>The object value.</returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
+ if (reader.TokenType == JsonToken.Null)
+ return null;
+
T value = Create(objectType);
if (value == null)
throw new JsonSerializationException("No object created.");
diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
index 1228bcc..3dfb147 100644
--- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
+++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
@@ -573,7 +573,7 @@ namespace Newtonsoft.Json.Serialization
}
catch (Exception ex)
{
- throw new JsonSerializationException("Could not convert string '{0}' to dictionary key type {1}. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex);
+ throw new JsonSerializationException("Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex);
}
CheckedRead(reader);
diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
index a50b4fa..4c9ea1d 100644
--- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
@@ -30,6 +30,7 @@ using System.Text;
using System.Globalization;
using System.ComponentModel;
using Newtonsoft.Json.Serialization;
+using System.Reflection;
#if !SILVERLIGHT
using System.Data.SqlTypes;
@@ -39,6 +40,63 @@ namespace Newtonsoft.Json.Utilities
{
internal static class ConvertUtils
{
+ internal struct TypeConvertKey : IEquatable<TypeConvertKey>
+ {
+ private readonly Type _initialType;
+ private readonly Type _targetType;
+
+ public Type InitialType
+ {
+ get { return _initialType; }
+ }
+
+ public Type TargetType
+ {
+ get { return _targetType; }
+ }
+
+ public TypeConvertKey(Type initialType, Type targetType)
+ {
+ _initialType = initialType;
+ _targetType = targetType;
+ }
+
+ public override int GetHashCode()
+ {
+ return _initialType.GetHashCode() ^ _targetType.GetHashCode();
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is TypeConvertKey))
+ return false;
+
+ return Equals((TypeConvertKey)obj);
+ }
+
+ public bool Equals(TypeConvertKey other)
+ {
+ return (_initialType == other._initialType && _targetType == other._targetType);
+ }
+ }
+
+ private static readonly ThreadSafeStore<TypeConvertKey, Func<object, object>> CastConverters =
+ new ThreadSafeStore<TypeConvertKey, Func<object, object>>(CreateCastConverter);
+
+ private static Func<object, object> CreateCastConverter(TypeConvertKey t)
+ {
+ MethodInfo castMethodInfo = t.TargetType.GetMethod("op_Implicit", new[] { t.InitialType });
+ if (castMethodInfo == null)
+ castMethodInfo = t.TargetType.GetMethod("op_Explicit", new[] { t.InitialType });
+
+ if (castMethodInfo == null)
+ return null;
+
+ MethodCall<object, object> call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(castMethodInfo);
+
+ return o => call(null, o);
+ }
+
public static bool CanConvertType(Type initialType, Type targetType, bool allowTypeNameToString)
{
ValidationUtils.ArgumentNotNull(initialType, "initialType");
@@ -387,12 +445,22 @@ namespace Newtonsoft.Json.Utilities
{
Type valueType = (value != null) ? value.GetType() : null;
- if (value != null && targetType.IsAssignableFrom(valueType))
- return value;
- else if (value == null && ReflectionUtils.IsNullable(targetType))
- return null;
+ if (value != null)
+ {
+ if (targetType.IsAssignableFrom(valueType))
+ return value;
+
+ Func<object, object> castConverter = CastConverters.Get(new TypeConvertKey(valueType, targetType));
+ if (castConverter != null)
+ return castConverter(value);
+ }
else
- throw new Exception("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, (initialType != null) ? initialType.ToString() : "{null}", targetType));
+ {
+ if (ReflectionUtils.IsNullable(targetType))
+ return null;
+ }
+
+ throw new Exception("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, (initialType != null) ? initialType.ToString() : "{null}", targetType));
}
#if !SILVERLIGHT
diff --git a/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
index 3bffe95..e1e6b91 100644
--- a/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
+++ b/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
@@ -66,7 +66,7 @@ namespace Newtonsoft.Json.Utilities
generator.MarkLabel(argsOk);
- if (!method.IsConstructor)
+ if (!method.IsConstructor && !method.IsStatic)
generator.PushInstance(method.DeclaringType);
for (int i = 0; i < args.Length; i++)