From 8956d3ca9cba20a85c0a61874f92b2c20dfc21f4 Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Wed, 18 Jan 2017 21:33:30 +0000 Subject: [PATCH 1/4] Fix issues that are variants of those #1182 (#1184) * Catch excessive objects in json being parsed, even if following a comment. * Include line info on excessive content for deserialisation. --- Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs | 25 ++++++++++ .../Linq/JObjectTests.cs | 25 ++++++++++ Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs | 25 ++++++++++ .../Serialization/JsonSerializerTest.cs | 47 ++++++++++++++++++- Src/Newtonsoft.Json/JsonConvert.cs | 10 +++- Src/Newtonsoft.Json/Linq/JArray.cs | 4 +- Src/Newtonsoft.Json/Linq/JObject.cs | 4 +- Src/Newtonsoft.Json/Linq/JToken.cs | 5 +- .../JsonSerializerInternalReader.cs | 2 +- 9 files changed, 137 insertions(+), 10 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs index 331a6e05..30880d6b 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs @@ -556,6 +556,31 @@ Parameter name: index"); Assert.AreEqual(3, (int)a[2]); } + [Test] + public void Parse_ExcessiveContentJustComments() + { + string json = @"[1,2,3]/*comment*/ +//Another comment."; + + JArray a = JArray.Parse(json); + + Assert.AreEqual(3, a.Count); + Assert.AreEqual(1, (int)a[0]); + Assert.AreEqual(2, (int)a[1]); + Assert.AreEqual(3, (int)a[2]); + } + + [Test] + public void Parse_ExcessiveContent() + { + string json = @"[1,2,3]/*comment*/ +//Another comment. +[]"; + + ExceptionAssert.Throws(() => JArray.Parse(json), + "Additional text encountered after finished reading JSON content: [. Path '', line 3, position 0."); + } + [Test] public void Parse_LineInfo() { diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index b39c7ca3..3bd1acee 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -1994,5 +1994,30 @@ Parameter name: arrayIndex"); Assert.AreEqual(2, (int)o["prop"][1]); Assert.AreEqual(3, (int)o["prop"][2]); } + + [Test] + public void Parse_ExcessiveContentJustComments() + { + string json = @"{'prop':[1,2,3]}/*comment*/ +//Another comment."; + + JObject o = JObject.Parse(json); + + Assert.AreEqual(3, o["prop"].Count()); + Assert.AreEqual(1, (int)o["prop"][0]); + Assert.AreEqual(2, (int)o["prop"][1]); + Assert.AreEqual(3, (int)o["prop"][2]); + } + + [Test] + public void Parse_ExcessiveContent() + { + string json = @"{'prop':[1,2,3]}/*comment*/ +//Another comment. +[]"; + + ExceptionAssert.Throws(() => JObject.Parse(json), + "Additional text encountered after finished reading JSON content: [. Path '', line 3, position 0."); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs index 57e4337a..63c0a038 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs @@ -1264,5 +1264,30 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(2, (int)o["prop"][1]); Assert.AreEqual(3, (int)o["prop"][2]); } + + [Test] + public void Parse_ExcessiveContentJustComments() + { + string json = @"{'prop':[1,2,3]}/*comment*/ +//Another comment."; + + JToken o = JToken.Parse(json); + + Assert.AreEqual(3, o["prop"].Count()); + Assert.AreEqual(1, (int)o["prop"][0]); + Assert.AreEqual(2, (int)o["prop"][1]); + Assert.AreEqual(3, (int)o["prop"][2]); + } + + [Test] + public void Parse_ExcessiveContent() + { + string json = @"{'prop':[1,2,3]}/*comment*/ +//Another comment. +{}"; + + ExceptionAssert.Throws(() => JToken.Parse(json), + "Additional text encountered after finished reading JSON content: {. Path '', line 3, position 0."); + } } } \ 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 25915659..d570ec46 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -8253,7 +8253,52 @@ lines.*/ reader.Read(); serializer.Deserialize(reader, typeof(MyType)); - }, "Additional text found in JSON string after finishing deserializing object."); + }, "Additional text found in JSON string after finishing deserializing object. Path '[1]', line 1, position 5."); + } + + [Test] + public void AdditionalContentAfterFinishCheckNotRequested() + { + string json = @"{ ""MyProperty"":{""Key"":""Value""}} A bunch of junk at the end of the json"; + + JsonSerializer serializer = new JsonSerializer(); + + var reader = new JsonTextReader(new StringReader(json)); + + MyType mt = (MyType)serializer.Deserialize(reader, typeof(MyType)); + Assert.AreEqual(1, mt.MyProperty.Count); + } + + [Test] + public void AdditionalContentAfterCommentsCheckNotRequested() + { + string json = @"{ ""MyProperty"":{""Key"":""Value""}} /*this is a comment */ +// this is also a comment +This is just junk, though."; + + JsonSerializer serializer = new JsonSerializer(); + + var reader = new JsonTextReader(new StringReader(json)); + + MyType mt = (MyType)serializer.Deserialize(reader, typeof(MyType)); + Assert.AreEqual(1, mt.MyProperty.Count); + } + + [Test] + public void AdditionalContentAfterComments() + { + string json = @"[{ ""MyProperty"":{""Key"":""Value""}} /*this is a comment */ +// this is also a comment +,{}"; + + JsonSerializer serializer = new JsonSerializer(); + serializer.CheckAdditionalContent = true; + var reader = new JsonTextReader(new StringReader(json)); + reader.Read(); + reader.Read(); + + ExceptionAssert.Throws(() => serializer.Deserialize(reader, typeof(MyType)), + "Additional text found in JSON string after finishing deserializing object. Path '[1]', line 3, position 2."); } [Test] diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index 22089c97..dd59b27d 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -962,9 +962,15 @@ namespace Newtonsoft.Json { jsonSerializer.Populate(jsonReader, target); - if (jsonReader.Read() && jsonReader.TokenType != JsonToken.Comment) + if (settings != null && settings.CheckAdditionalContent) { - throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object."); + while (jsonReader.Read()) + { + if (jsonReader.TokenType != JsonToken.Comment) + { + throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); + } + } } } } diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs index c6c117f3..17b1c150 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.cs @@ -176,9 +176,9 @@ namespace Newtonsoft.Json.Linq { JArray a = Load(reader, settings); - if (reader.Read() && reader.TokenType != JsonToken.Comment) + while (reader.Read()) { - throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content."); + // Any content encountered here other than a comment will throw in the reader. } return a; diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 7cb6505c..4a981d71 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -426,9 +426,9 @@ namespace Newtonsoft.Json.Linq { JObject o = Load(reader, settings); - if (reader.Read() && reader.TokenType != JsonToken.Comment) + while (reader.Read()) { - throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content."); + // Any content encountered here other than a comment will throw in the reader. } return o; diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 2e6d13fb..5414a0ab 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -2187,11 +2187,12 @@ namespace Newtonsoft.Json.Linq { JToken t = Load(reader, settings); - if (reader.Read() && reader.TokenType != JsonToken.Comment) + while (reader.Read()) { - throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content."); + // Any content encountered here other than a comment will throw in the reader. } + return t; } } diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 5ff29e78..63218a2c 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -173,7 +173,7 @@ namespace Newtonsoft.Json.Serialization { if (reader.TokenType != JsonToken.Comment) { - throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object."); + throw JsonSerializationException.Create(reader, "Additional text found in JSON string after finishing deserializing object."); } } } From 56e3d7575bc075cb7c5d1809607d98c81d49ad12 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Thu, 19 Jan 2017 11:49:09 +1300 Subject: [PATCH 2/4] -Fixed deserializing non-string values in some XML nodes --- .../Converters/XmlNodeConverterTest.cs | 41 +++++++++++++++++++ .../Converters/XmlNodeConverter.cs | 24 +++++------ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs index ed8fe976..2c7a861d 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs @@ -2913,6 +2913,47 @@ namespace Newtonsoft.Json.Tests.Converters var deserialized = JsonConvert.DeserializeObject(json); Assert.AreEqual(@"", deserialized.ToString()); } + + public class Model + { + public XElement Document { get; set; } + } + + [Test] + public void DeserializeDateInElementText() + { + Model model = new Model(); + model.Document = new XElement("Value", new XAttribute("foo", "bar")) + { + Value = "2001-01-01T11:11:11" + }; + + var serializer = JsonSerializer.Create(new JsonSerializerSettings + { + Converters = new List(new[] { new XmlNodeConverter() }) + }); + + var json = new StringBuilder(1024); + + using (var stringWriter = new StringWriter(json, CultureInfo.InvariantCulture)) + using (var jsonWriter = new JsonTextWriter(stringWriter)) + { + jsonWriter.Formatting = Formatting.None; + serializer.Serialize(jsonWriter, model); + + Assert.AreEqual(@"{""Document"":{""Value"":{""@foo"":""bar"",""#text"":""2001-01-01T11:11:11""}}}", json.ToString()); + } + + using (var stringReader = new StringReader(json.ToString())) + using (var jsonReader = new JsonTextReader(stringReader)) + { + var document = (XDocument)serializer.Deserialize(jsonReader, typeof(XDocument)); + + StringAssert.AreEqual(@" + 2001-01-01T11:11:11 +", document.ToString()); + } + } #endif } } diff --git a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs index 3521054e..b8fe7400 100644 --- a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs @@ -1680,16 +1680,16 @@ namespace Newtonsoft.Json.Converters switch (propertyName) { case TextName: - currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString())); + currentNode.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader))); break; case CDataName: - currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString())); + currentNode.AppendChild(document.CreateCDataSection(ConvertTokenToXmlValue(reader))); break; case WhitespaceName: - currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString())); + currentNode.AppendChild(document.CreateWhitespace(ConvertTokenToXmlValue(reader))); break; case SignificantWhitespaceName: - currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString())); + currentNode.AppendChild(document.CreateSignificantWhitespace(ConvertTokenToXmlValue(reader))); break; default: // processing instructions and the xml declaration start with ? @@ -2072,15 +2072,15 @@ namespace Newtonsoft.Json.Converters { case "@version": reader.Read(); - version = reader.Value.ToString(); + version = ConvertTokenToXmlValue(reader); break; case "@encoding": reader.Read(); - encoding = reader.Value.ToString(); + encoding = ConvertTokenToXmlValue(reader); break; case "@standalone": reader.Read(); - standalone = reader.Value.ToString(); + standalone = ConvertTokenToXmlValue(reader); break; default: throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); @@ -2092,7 +2092,7 @@ namespace Newtonsoft.Json.Converters } else { - IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString()); + IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), ConvertTokenToXmlValue(reader)); currentNode.AppendChild(instruction); } } @@ -2109,19 +2109,19 @@ namespace Newtonsoft.Json.Converters { case "@name": reader.Read(); - name = reader.Value.ToString(); + name = ConvertTokenToXmlValue(reader); break; case "@public": reader.Read(); - publicId = reader.Value.ToString(); + publicId = ConvertTokenToXmlValue(reader); break; case "@system": reader.Read(); - systemId = reader.Value.ToString(); + systemId = ConvertTokenToXmlValue(reader); break; case "@internalSubset": reader.Read(); - internalSubset = reader.Value.ToString(); + internalSubset = ConvertTokenToXmlValue(reader); break; default: throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); From 55afb9aa72a07494aa35015dd2a29f7e9643127f Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Thu, 19 Jan 2017 14:19:52 +1300 Subject: [PATCH 3/4] -Added AutoCompleteOnClose to JsonWriter to control whether JSON is auto-completed on JsonWriter.Close --- .../Bson/BsonWriterTests.cs | 57 +++++++++++++++++++ .../JsonTextWriterTest.cs | 45 +++++++++++++++ Src/Newtonsoft.Json/Bson/BsonWriter.cs | 1 + .../Converters/XmlNodeConverter.cs | 2 - Src/Newtonsoft.Json/JsonTextWriter.cs | 1 + Src/Newtonsoft.Json/JsonWriter.cs | 17 +++++- Src/Newtonsoft.Json/Linq/JTokenWriter.cs | 1 + 7 files changed, 120 insertions(+), 4 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs index c53bcd9a..3c4b04e9 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonWriterTests.cs @@ -882,6 +882,63 @@ namespace Newtonsoft.Json.Tests.Bson Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); Assert.IsNull(reader.ReadAsBytes()); } + + [Test] + public void WriteEndOnProperty() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + writer.WriteEnd(); + + Assert.AreEqual("0B-00-00-00-0A-42-6C-61-68-00-00", (BitConverter.ToString(ms.ToArray()))); + } + + [Test] + public void WriteEndOnProperty_Close() + { + MemoryStream ms = new MemoryStream(); + BsonWriter writer = new BsonWriter(ms); + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + writer.Close(); + + Assert.AreEqual("0B-00-00-00-0A-42-6C-61-68-00-00", (BitConverter.ToString(ms.ToArray()))); + } + + [Test] + public void WriteEndOnProperty_Dispose() + { + MemoryStream ms = new MemoryStream(); + using (BsonWriter writer = new BsonWriter(ms)) + { + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + } + + Assert.AreEqual("0B-00-00-00-0A-42-6C-61-68-00-00", (BitConverter.ToString(ms.ToArray()))); + } + + [Test] + public void AutoCompleteOnClose_False() + { + MemoryStream ms = new MemoryStream(); + using (BsonWriter writer = new BsonWriter(ms)) + { + writer.AutoCompleteOnClose = false; + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + + writer.Flush(); + } + + // nothing is written because a BSON document needs to be completed before it can be written + Assert.AreEqual(string.Empty, (BitConverter.ToString(ms.ToArray()))); + } #endif } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs index fb8afb4c..99c9d386 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs @@ -1310,6 +1310,51 @@ _____'propertyName': NaN, Assert.AreEqual("{'Blah':null}", sw.ToString()); } + [Test] + public void WriteEndOnProperty_Close() + { + StringWriter sw = new StringWriter(); + JsonTextWriter writer = new JsonTextWriter(sw); + writer.QuoteChar = '\''; + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + writer.Close(); + + Assert.AreEqual("{'Blah':null}", sw.ToString()); + } + + [Test] + public void WriteEndOnProperty_Dispose() + { + StringWriter sw = new StringWriter(); + using (JsonTextWriter writer = new JsonTextWriter(sw)) + { + writer.QuoteChar = '\''; + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + } + + Assert.AreEqual("{'Blah':null}", sw.ToString()); + } + + [Test] + public void AutoCompleteOnClose_False() + { + StringWriter sw = new StringWriter(); + using (JsonTextWriter writer = new JsonTextWriter(sw)) + { + writer.AutoCompleteOnClose = false; + writer.QuoteChar = '\''; + + writer.WriteStartObject(); + writer.WritePropertyName("Blah"); + } + + Assert.AreEqual("{'Blah':", sw.ToString()); + } + #if !NET20 [Test] public void QuoteChar() diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index e4e277eb..a3de3a2a 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -172,6 +172,7 @@ namespace Newtonsoft.Json.Bson /// /// Closes this writer. /// If is set to true, the underlying is also closed. + /// If is set to true, the JSON is auto-completed. /// public override void Close() { diff --git a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs index b8fe7400..6775bbb1 100644 --- a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs @@ -1652,8 +1652,6 @@ namespace Newtonsoft.Json.Converters if (!string.IsNullOrEmpty(DeserializeRootElementName)) { - //rootNode = document.CreateElement(DeserializeRootElementName); - //document.AppendChild(rootNode); ReadElement(reader, document, rootNode, DeserializeRootElementName, manager); } else diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 560d5d23..743d760e 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -178,6 +178,7 @@ namespace Newtonsoft.Json /// /// Closes this writer. /// If is set to true, the underlying is also closed. + /// If is set to true, the JSON is auto-completed. /// public override void Close() { diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index fa3a13ef..34a2d6b0 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -126,6 +126,14 @@ namespace Newtonsoft.Json /// public bool CloseOutput { get; set; } + /// + /// Gets or sets a value indicating whether the JSON should be auto-completed when this writer is closed. + /// + /// + /// true to auto-complete the JSON when this writer is closed; otherwise false. The default is true. + /// + public bool AutoCompleteOnClose { get; set; } + /// /// Gets the top. /// @@ -339,6 +347,7 @@ namespace Newtonsoft.Json _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; CloseOutput = true; + AutoCompleteOnClose = true; } internal void UpdateScopeWithFinishedValue() @@ -393,11 +402,15 @@ namespace Newtonsoft.Json /// /// Closes this writer. - /// If is set to true, the destination is also closed. + /// If is set to true, the destination is also closed. + /// If is set to true, the JSON is auto-completed. /// public virtual void Close() { - AutoCompleteAll(); + if (AutoCompleteOnClose) + { + AutoCompleteAll(); + } } /// diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index 4d86d563..8750bc66 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -96,6 +96,7 @@ namespace Newtonsoft.Json.Linq /// /// Closes this writer. + /// If is set to true, the JSON is auto-completed. /// /// /// Setting to true has no additional effect, since the underlying is a type that cannot be closed. From 2e7b24e9b1873a615bbc8ae2302fd3d174cdb9f2 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Thu, 19 Jan 2017 17:43:07 +1300 Subject: [PATCH 4/4] -Added support for TypeConverters to netstandard1.0+ --- Build/Newtonsoft.Json.nuspec | 2 + Src/Newtonsoft.Json.Tests/PerformanceTests.cs | 2 +- .../Serialization/JsonSerializerTest.cs | 113 ++++++++++++++++++ Src/Newtonsoft.Json.Tests/project.json | 1 + .../Newtonsoft.Json.Net20.csproj | 2 +- .../Newtonsoft.Json.Net35.csproj | 2 +- .../Newtonsoft.Json.Net40.csproj | 2 +- Src/Newtonsoft.Json/Newtonsoft.Json.csproj | 3 +- .../Serialization/DefaultContractResolver.cs | 16 +-- .../JsonSerializerInternalWriter.cs | 17 +-- .../Serialization/JsonTypeReflector.cs | 30 +++-- Src/Newtonsoft.Json/Utilities/ConvertUtils.cs | 15 +-- Src/Newtonsoft.Json/project.json | 4 + 13 files changed, 161 insertions(+), 48 deletions(-) diff --git a/Build/Newtonsoft.Json.nuspec b/Build/Newtonsoft.Json.nuspec index f20220e4..84cb66ee 100644 --- a/Build/Newtonsoft.Json.nuspec +++ b/Build/Newtonsoft.Json.nuspec @@ -21,6 +21,7 @@ + @@ -46,6 +47,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index bde64843..980eedb6 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -240,7 +240,7 @@ namespace Newtonsoft.Json.Tests { var json = System.IO.File.ReadAllText("large.json"); - BenchmarkDeserializeMethod>(SerializeMethod.JsonNet, json, Iterations / 10, false); + BenchmarkDeserializeMethod>(SerializeMethod.JsonNet, json, Math.Min(Iterations, 10), false); } [Test] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index d570ec46..38a31ca3 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -9089,6 +9089,119 @@ This is just junk, though."; } #endif +#if !(PORTABLE || PORTABLE40 || DNXCORE50) || NETSTANDARD1_0 || NETSTANDARD1_1 + [Test] + public void SerializeDictionaryWithStructKey_Custom() + { + string json = JsonConvert.SerializeObject( + new Dictionary { { new TypeConverterSize(1, 2), new TypeConverterSize(3, 4) } } + ); + + Assert.AreEqual(@"{""1, 2"":""3, 4""}", json); + + Dictionary d = JsonConvert.DeserializeObject>(json); + + Assert.AreEqual(new TypeConverterSize(1, 2), d.Keys.First()); + Assert.AreEqual(new TypeConverterSize(3, 4), d.Values.First()); + } + + [TypeConverter(typeof(TypeConverterSizeConverter))] + public struct TypeConverterSize + { + public static readonly TypeConverterSize Empty; + private int _width; + private int _height; + + public TypeConverterSize(int width, int height) + { + _width = width; + _height = height; + } + + public int Width + { + get { return _width; } + set { _width = value; } + } + + public int Height + { + get { return _height; } + set { _height = value; } + } + } + + public class TypeConverterSizeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return ((sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType)); + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return base.CanConvertTo(context, destinationType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + string str = value as string; + if (str == null) + { + return base.ConvertFrom(context, culture, value); + } + string str2 = str.Trim(); + if (str2.Length == 0) + { + return null; + } + if (culture == null) + { + culture = CultureInfo.CurrentCulture; + } + string[] strArray = str2.Split(','); + int[] numArray = new int[strArray.Length]; + TypeConverter converter = TypeDescriptor.GetConverter(typeof(int)); + for (int i = 0; i < numArray.Length; i++) + { + numArray[i] = (int)converter.ConvertFromString(context, culture, strArray[i]); + } + if (numArray.Length == 2) + { + return new TypeConverterSize(numArray[0], numArray[1]); + } + + throw new ArgumentException("Bad format."); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == null) + { + throw new ArgumentNullException("destinationType"); + } + if (value is TypeConverterSize) + { + if (destinationType == typeof(string)) + { + TypeConverterSize size = (TypeConverterSize)value; + if (culture == null) + { + culture = CultureInfo.CurrentCulture; + } + TypeConverter converter = TypeDescriptor.GetConverter(typeof(int)); + string[] strArray = new string[2]; + int num = 0; + strArray[num++] = converter.ConvertToString(context, culture, size.Width); + strArray[num++] = converter.ConvertToString(context, culture, size.Height); + return string.Join(", ", strArray); + } + } + return base.ConvertTo(context, culture, value, destinationType); + } + } +#endif + [Test] public void DeserializeCustomReferenceResolver() { diff --git a/Src/Newtonsoft.Json.Tests/project.json b/Src/Newtonsoft.Json.Tests/project.json index 9f780328..fbf2c3b6 100644 --- a/Src/Newtonsoft.Json.Tests/project.json +++ b/Src/Newtonsoft.Json.Tests/project.json @@ -95,6 +95,7 @@ "System.Xml.XmlSerializer": "4.0.11", "System.Runtime.Serialization.Json": "4.0.2", "System.Runtime.Serialization.Xml": "4.1.1", + "System.ComponentModel.TypeConverter": "4.1.0", "xunit": "2.1.0", "dotnet-test-xunit": "2.2.0-preview2-build1029" }, diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index 7374260c..7ffc0644 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -43,7 +43,7 @@ false true NET20;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_DB_NULL_TYPE_CODE;HAVE_EMPTY_TYPES;HAVE_FULL_REFLECTION;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_MEMORY_BARRIER; - HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_TRACE_WRITER;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_XML_DOCUMENT + HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_XML_DOCUMENT true diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj index e3e6e7ee..9ba9b0c0 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -44,7 +44,7 @@ true - NET35;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_FULL_REFLECTION;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_LINQ;HAVE_MEMORY_BARRIER; HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_XLINQ;HAVE_XML_DOCUMENT + NET35;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_FULL_REFLECTION;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_XLINQ;HAVE_XML_DOCUMENT true diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj index fb80dd58..dceefe54 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj @@ -44,7 +44,7 @@ true - NET40;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TPL;HAVE_TRACE_WRITER;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT + NET40;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TPL;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT true diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index ee828752..65c15493 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -11,8 +11,7 @@ Newtonsoft.Json v4.5 512 - HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_IMMUTABLE_COLLECTIONS;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE; - HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TPL;HAVE_TRACE_WRITER;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT + HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_IMMUTABLE_COLLECTIONS;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TPL;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT true diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 945513e2..0a22af69 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -1233,19 +1233,11 @@ namespace Newtonsoft.Json.Serialization internal static bool CanConvertToString(Type type) { -#if HAVE_COMPONENT_MODEL - TypeConverter converter = ConvertUtils.GetConverter(type); - - // use the objectType's TypeConverter if it has one and can convert to a string - if (converter != null - && !(converter is ComponentConverter) - && !(converter is ReferenceConverter) - && converter.GetType() != typeof(TypeConverter)) +#if HAVE_TYPE_DESCRIPTOR + TypeConverter converter; + if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out converter)) { - if (converter.CanConvertTo(typeof(string))) - { - return true; - } + return true; } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 2eaa8646..9192cb2b 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -379,19 +379,12 @@ namespace Newtonsoft.Json.Serialization internal static bool TryConvertToString(object value, Type type, out string s) { -#if HAVE_COMPONENT_MODEL - TypeConverter converter = ConvertUtils.GetConverter(type); - - // use the objectType's TypeConverter if it has one and can convert to a string - if (converter != null - && !(converter is ComponentConverter) - && converter.GetType() != typeof(TypeConverter)) +#if HAVE_TYPE_DESCRIPTOR + TypeConverter converter; + if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out converter)) { - if (converter.CanConvertTo(typeof(string))) - { - s = converter.ConvertToInvariantString(value); - return true; - } + s = converter.ConvertToInvariantString(value); + return true; } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 62ab8e5a..012dd9c2 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -69,6 +69,29 @@ namespace Newtonsoft.Json.Serialization return CachedAttributeGetter.GetAttribute(attributeProvider); } +#if HAVE_TYPE_DESCRIPTOR + public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter typeConverter) + { + typeConverter = TypeDescriptor.GetConverter(type); + + // use the objectType's TypeConverter if it has one and can convert to a string + if (typeConverter != null) + { + Type converterType = typeConverter.GetType(); + + if (converterType.FullName != "System.ComponentModel.ComponentConverter" + && converterType.FullName != "System.ComponentModel.ReferenceConverter" + && converterType != typeof(TypeConverter)) + { + return typeConverter.CanConvertTo(typeof(string)); + } + + } + + return false; + } +#endif + #if HAVE_DATA_CONTRACTS public static DataContractAttribute GetDataContractAttribute(Type type) { @@ -245,13 +268,6 @@ namespace Newtonsoft.Json.Serialization }; } -#if HAVE_COMPONENT_MODEL - public static TypeConverter GetTypeConverter(Type type) - { - return TypeDescriptor.GetConverter(type); - } -#endif - #if !(NET20 || DOTNET) private static Type GetAssociatedMetadataType(Type type) { diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index 17d5c1b8..fb2eb8a4 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -559,9 +559,9 @@ namespace Newtonsoft.Json.Utilities } #endif -#if HAVE_COMPONENT_MODEL +#if HAVE_TYPE_DESCRIPTOR // see if source or target types have a TypeConverter that converts between the two - TypeConverter toConverter = GetConverter(initialType); + TypeConverter toConverter = TypeDescriptor.GetConverter(initialType); if (toConverter != null && toConverter.CanConvertTo(targetType)) { @@ -569,7 +569,7 @@ namespace Newtonsoft.Json.Utilities return ConvertResult.Success; } - TypeConverter fromConverter = GetConverter(targetType); + TypeConverter fromConverter = TypeDescriptor.GetConverter(targetType); if (fromConverter != null && fromConverter.CanConvertFrom(initialType)) { @@ -707,19 +707,12 @@ namespace Newtonsoft.Json.Utilities } #endif -#if HAVE_COMPONENT_MODEL - internal static TypeConverter GetConverter(Type t) - { - return JsonTypeReflector.GetTypeConverter(t); - } -#endif - public static bool VersionTryParse(string input, out Version result) { #if HAVE_VERSION_TRY_PARSE return Version.TryParse(input, out result); #else - // improve failure performance with regex? + // improve failure performance with regex? try { result = new Version(input); diff --git a/Src/Newtonsoft.Json/project.json b/Src/Newtonsoft.Json/project.json index 31faf690..403269da 100644 --- a/Src/Newtonsoft.Json/project.json +++ b/Src/Newtonsoft.Json/project.json @@ -172,6 +172,7 @@ "HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE", "HAVE_TIME_ZONE_INFO", "HAVE_TPL", + "HAVE_TYPE_DESCRIPTOR", "HAVE_UNICODE_SURROGATE_DETECTION", "HAVE_VARIANT_TYPE_PARAMETERS", "HAVE_VERSION_TRY_PARSE", @@ -181,6 +182,7 @@ "dependencies": { "Microsoft.CSharp": "4.0.1", "System.Collections": "4.0.11", + "System.ComponentModel.TypeConverter": "4.1.0", "System.Diagnostics.Debug": "4.0.11", "System.Dynamic.Runtime": "4.0.11", "System.Globalization": "4.0.11", @@ -232,6 +234,7 @@ "HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE", "HAVE_TIME_ZONE_INFO", "HAVE_TPL", + "HAVE_TYPE_DESCRIPTOR", "HAVE_UNICODE_SURROGATE_DETECTION", "HAVE_VARIANT_TYPE_PARAMETERS", "HAVE_VERSION_TRY_PARSE", @@ -241,6 +244,7 @@ "dependencies": { "Microsoft.CSharp": "4.0.1", "System.Collections": "4.0.11", + "System.ComponentModel.TypeConverter": "4.1.0", "System.Diagnostics.Debug": "4.0.11", "System.Dynamic.Runtime": "4.0.11", "System.Globalization": "4.0.11",