diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index 8b49e92d..24b5d56b 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -519,5 +519,42 @@ Parameter name: arrayIndex")] ""o"": ""
\r\n
\r\n asdf
\r\n 0\r\n
\r\n
\r\n

\r\n 444444444\r\n

\r\n
\r\n
\r\n
\r\n
"" }", o.ToString()); } + + [Test] + public void ImplicitValueConversions() + { + JObject moss = new JObject(); + moss["FirstName"] = new JValue("Maurice"); + moss["LastName"] = new JValue("Moss"); + moss["BirthDate"] = new JValue(new DateTime(1977, 12, 30)); + moss["Department"] = new JValue("IT"); + moss["JobTitle"] = new JValue("Support"); + + Console.WriteLine(moss.ToString()); + //{ + // "FirstName": "Maurice", + // "LastName": "Moss", + // "BirthDate": "\/Date(252241200000+1300)\/", + // "Department": "IT", + // "JobTitle": "Support" + //} + + + JObject jen = new JObject(); + jen["FirstName"] = "Jen"; + jen["LastName"] = "Barber"; + jen["BirthDate"] = new DateTime(1978, 3, 15); + jen["Department"] = "IT"; + jen["JobTitle"] = "Manager"; + + Console.WriteLine(jen.ToString()); + //{ + // "FirstName": "Jen", + // "LastName": "Barber", + // "BirthDate": "\/Date(258721200000+1300)\/", + // "Department": "IT", + // "JobTitle": "Manager" + //} + } } } diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs index d258a734..c5afb059 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs @@ -280,6 +280,8 @@ namespace Newtonsoft.Json.Tests.Linq Assert.IsTrue(JToken.DeepEquals(new JValue(float.MaxValue), (JValue)(float?)float.MaxValue)); Assert.IsTrue(JToken.DeepEquals(new JValue(double.MaxValue), (JValue)(double?)double.MaxValue)); Assert.IsTrue(JToken.DeepEquals(new JValue((object)null), (JValue)(double?)null)); + + Assert.IsFalse(JToken.DeepEquals(new JValue((object)null), (JValue)(object)null)); } [Test] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs index df1b0224..f661df44 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs @@ -231,5 +231,59 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameHandling = TypeNameHandling.Objects }); } + + public interface ICorrelatedMessage + { + string CorrelationId { get; set; } + } + + public class SendHttpRequest : ICorrelatedMessage + { + public SendHttpRequest() + { + RequestEncoding = "UTF-8"; + Method = "GET"; + } + public string Method { get; set; } + public Dictionary Headers { get; set; } + public string Url { get; set; } + public Dictionary RequestData; + public string RequestBodyText { get; set; } + public string User { get; set; } + public string Passwd { get; set; } + public string RequestEncoding { get; set; } + public string CorrelationId { get; set; } + } + + [Test] + public void DeserializeGenericTypeName() + { + string typeName = typeof(SendHttpRequest).AssemblyQualifiedName; + + string json = @"{ +""$type"": """ + typeName + @""", +""RequestData"": { +""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"", +""Id"": ""siedemnaƛcie"", +""X"": ""323"" +}, +""Method"": ""GET"", +""Url"": ""http://www.onet.pl"", +""RequestEncoding"": ""UTF-8"", +""CorrelationId"": ""xyz"" +}"; + + ICorrelatedMessage message = JsonConvert.DeserializeObject(json, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + + Assert.IsInstanceOfType(typeof(SendHttpRequest), message); + + SendHttpRequest request = (SendHttpRequest) message; + Assert.AreEqual("xyz", request.CorrelationId); + Assert.AreEqual(2, request.RequestData.Count); + Assert.AreEqual("siedemnaƛcie", request.RequestData["Id"]); + } } } diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs index 1f3a5a5b..2007b9e3 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerReader.cs @@ -223,19 +223,9 @@ namespace Newtonsoft.Json.Serialization if (_serializer.TypeNameHandling != TypeNameHandling.None) { - int delimiterIndex = qualifiedTypeName.IndexOf(','); string typeName; string assemblyName; - if (delimiterIndex != -1) - { - typeName = qualifiedTypeName.Substring(0, delimiterIndex).Trim(); - assemblyName = qualifiedTypeName.Substring(delimiterIndex + 1, qualifiedTypeName.Length - delimiterIndex - 1).Trim(); - } - else - { - typeName = qualifiedTypeName; - assemblyName = null; - } + ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName, out typeName, out assemblyName); Type specifiedType; try diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index 6bb948ba..38417e1a 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -632,5 +632,48 @@ namespace Newtonsoft.Json.Utilities return match.Invoke(args); #endif } + + public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName) + { + int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName); + + if (assemblyDelimiterIndex != null) + { + typeName = fullyQualifiedTypeName.Substring(0, assemblyDelimiterIndex.Value).Trim(); + assemblyName = fullyQualifiedTypeName.Substring(assemblyDelimiterIndex.Value + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.Value - 1).Trim(); + } + else + { + typeName = fullyQualifiedTypeName; + assemblyName = null; + } + + } + + private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName) + { + // we need to get the first comma following all surrounded in brackets because of generic types + // e.g. System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + int scope = 0; + for (int i = 0; i < fullyQualifiedTypeName.Length; i++) + { + char current = fullyQualifiedTypeName[i]; + switch (current) + { + case '[': + scope++; + break; + case ']': + scope--; + break; + case ',': + if (scope == 0) + return i; + break; + } + } + + return null; + } } } \ No newline at end of file