From fc6c041196b7a1b8f0095a8d7e48ec65de695236 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Tue, 11 May 2010 07:49:02 +0000 Subject: [PATCH] -Performance -Add CLSCompliant attributes -Fix BSON string reading bug --- .../Bson/BsonReaderTests.cs | 51 ++++++++++++ Src/Newtonsoft.Json.Tests/PerformanceTests.cs | 60 ++++++++++++-- Src/Newtonsoft.Json/Bson/BsonReader.cs | 2 +- Src/Newtonsoft.Json/Bson/BsonWriter.cs | 4 + Src/Newtonsoft.Json/JsonConvert.cs | 4 + Src/Newtonsoft.Json/JsonTextWriter.cs | 4 + Src/Newtonsoft.Json/JsonWriter.cs | 8 ++ Src/Newtonsoft.Json/Linq/JContainer.cs | 2 +- Src/Newtonsoft.Json/Linq/JObject.cs | 2 +- Src/Newtonsoft.Json/Linq/JToken.cs | 10 +++ Src/Newtonsoft.Json/Linq/JTokenWriter.cs | 4 + Src/Newtonsoft.Json/Linq/JValue.cs | 83 +++++++++---------- .../Properties/AssemblyInfo.cs | 5 +- 13 files changed, 184 insertions(+), 55 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index e56ebef5..17b9a4bb 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -1013,5 +1013,56 @@ namespace Newtonsoft.Json.Tests.Bson Assert.IsFalse(reader.Read()); } + + [Test] + public void CanRoundTripStackOverflowData() + { + var doc = + @"{ +""AboutMe"": ""

I'm the Director for Research and Development for ProPhoenix, a public safety software company. This position allows me to investigate new and existing technologies and incorporate them into our product line, with the end goal being to help public safety agencies to do their jobs more effeciently and safely.

\r\n\r\n

I'm an advocate for PowerShell, as I believe it encourages administrative best practices and allows developers to provide additional access to their applications, without needing to explicity write code for each administrative feature. Part of my advocacy for PowerShell includes my blog, appearances on various podcasts, and acting as a Community Director for PowerShellCommunity.Org

\r\n\r\n

I’m also a co-host of Mind of Root (a weekly audio podcast about systems administration, tech news, and topics).

\r\n"", +""WebsiteUrl"": ""http://blog.usepowershell.com"" +}"; + JObject parsed = JObject.Parse(doc); + var memoryStream = new MemoryStream(); + var bsonWriter = new BsonWriter(memoryStream); + parsed.WriteTo(bsonWriter); + bsonWriter.Flush(); + memoryStream.Position = 0; + + BsonReader reader = new BsonReader(memoryStream); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.StartObject, reader.TokenType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); + Assert.AreEqual("AboutMe", reader.Value); + Assert.AreEqual(typeof(string), reader.ValueType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.String, reader.TokenType); + Assert.AreEqual(@"

I'm the Director for Research and Development for ProPhoenix, a public safety software company. This position allows me to investigate new and existing technologies and incorporate them into our product line, with the end goal being to help public safety agencies to do their jobs more effeciently and safely.

+ +

I'm an advocate for PowerShell, as I believe it encourages administrative best practices and allows developers to provide additional access to their applications, without needing to explicity write code for each administrative feature. Part of my advocacy for PowerShell includes my blog, appearances on various podcasts, and acting as a Community Director for PowerShellCommunity.Org

+ +

I’m also a co-host of Mind of Root (a weekly audio podcast about systems administration, tech news, and topics).

+", reader.Value); + Assert.AreEqual(typeof(string), reader.ValueType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.PropertyName, reader.TokenType); + Assert.AreEqual("WebsiteUrl", reader.Value); + Assert.AreEqual(typeof(string), reader.ValueType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.String, reader.TokenType); + Assert.AreEqual("http://blog.usepowershell.com", reader.Value); + Assert.AreEqual(typeof(string), reader.ValueType); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(JsonToken.EndObject, reader.TokenType); + + Assert.IsFalse(reader.Read()); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index 038e3617..4555ec7f 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -14,6 +14,7 @@ using System.Text; using Newtonsoft.Json.Bson; using System.Runtime.Serialization.Formatters.Binary; using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Converters; namespace Newtonsoft.Json.Tests { @@ -442,17 +443,17 @@ namespace Newtonsoft.Json.Tests switch (method) { case SerializeMethod.JsonNet: - return DeserializeJsonNet((string) json); + return DeserializeJsonNet((string)json); case SerializeMethod.JsonNetBinary: - return DeserializeJsonNetBinary((byte[]) json); + return DeserializeJsonNetBinary((byte[])json); case SerializeMethod.BinaryFormatter: - return DeserializeBinaryFormatter((byte[]) json); + return DeserializeBinaryFormatter((byte[])json); case SerializeMethod.JavaScriptSerializer: - return DeserializeWebExtensions((string) json); + return DeserializeWebExtensions((string)json); case SerializeMethod.DataContractSerializer: - return DeserializeDataContract((string) json); + return DeserializeDataContract((string)json); case SerializeMethod.DataContractJsonSerializer: - return DeserializeDataContractJson((string) json); + return DeserializeDataContractJson((string)json); default: throw new ArgumentOutOfRangeException("method"); } @@ -462,8 +463,8 @@ namespace Newtonsoft.Json.Tests { MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)); - DataContractSerializer serializer = new DataContractSerializer(typeof (T)); - return (T) serializer.ReadObject(ms); + DataContractSerializer serializer = new DataContractSerializer(typeof(T)); + return (T)serializer.ReadObject(ms); } private T DeserializeBinaryFormatter(byte[] bytes) @@ -487,7 +488,7 @@ namespace Newtonsoft.Json.Tests Integer = int.MaxValue, Text = "The quick red fox jumped over the lazy dog." }; - + if (rootValue == null) rootValue = currentValue; if (parentValue != null) @@ -498,6 +499,47 @@ namespace Newtonsoft.Json.Tests BenchmarkSerializeMethod(SerializeMethod.JsonNetBinary, rootValue); } + + [Test] + public void JObjectToString() + { + JObject test = JObject.Parse(JsonText); + IsoDateTimeConverter isoDateTimeConverter = null;// = new IsoDateTimeConverter(); + + TimeOperation(() => + { + for (int i = 0; i < 5000; i++) + { + test["dummy"] = new JValue(i); + Encoding.UTF8.GetBytes(test.ToString(Formatting.None)); + } + return null; + }, "JObject.ToString"); + } + + [Test] + public void JObjectToString2() + { + JObject test = JObject.Parse(JsonText); + IsoDateTimeConverter isoDateTimeConverter = null;// = new IsoDateTimeConverter(); + MemoryStream ms = new MemoryStream(); + + TimeOperation(() => + { + for (int i = 0; i < 5000; i++) + { + test["dummy"] = new JValue(i); + ms.Seek(0, SeekOrigin.Begin); + JsonTextWriter jsonTextWriter = new JsonTextWriter(new StreamWriter(ms)); + test.WriteTo(jsonTextWriter); + jsonTextWriter.Flush(); + ms.ToArray(); + + //Encoding.UTF8.GetBytes(test.ToString(Formatting.None)); + } + return null; + }, "JObject.ToString"); + } } public class LargeRecursiveTestClass diff --git a/Src/Newtonsoft.Json/Bson/BsonReader.cs b/Src/Newtonsoft.Json/Bson/BsonReader.cs index 710fe961..852fb20e 100644 --- a/Src/Newtonsoft.Json/Bson/BsonReader.cs +++ b/Src/Newtonsoft.Json/Bson/BsonReader.cs @@ -577,7 +577,7 @@ namespace Newtonsoft.Json.Bson { int count = ((length - totalBytesRead) > MaxCharBytesSize - offset) ? MaxCharBytesSize - offset - : length - totalBytesRead; + : length - totalBytesRead - offset; int byteCount = _reader.BaseStream.Read(_byteBuffer, offset, count); diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index 91c328b5..53821221 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -228,6 +228,7 @@ namespace Newtonsoft.Json.Bson /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(uint value) { if (value > int.MaxValue) @@ -251,6 +252,7 @@ namespace Newtonsoft.Json.Bson /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(ulong value) { if (value > long.MaxValue) @@ -304,6 +306,7 @@ namespace Newtonsoft.Json.Bson /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); @@ -334,6 +337,7 @@ namespace Newtonsoft.Json.Bson /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index 24a38e3a..40bdff45 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -255,6 +255,7 @@ namespace Newtonsoft.Json /// /// The value to convert. /// A JSON string representation of the . + [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); @@ -265,6 +266,7 @@ namespace Newtonsoft.Json /// /// The value to convert. /// A JSON string representation of the . + [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); @@ -285,6 +287,7 @@ namespace Newtonsoft.Json /// /// The value to convert. /// A JSON string representation of the . + [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); @@ -341,6 +344,7 @@ namespace Newtonsoft.Json /// /// The value to convert. /// A JSON string representation of the . + [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 12ccea4a..c233722e 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -302,6 +302,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(uint value) { base.WriteValue(value); @@ -322,6 +323,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(ulong value) { base.WriteValue(value); @@ -372,6 +374,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); @@ -402,6 +405,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index 2a18d29a..374a9c9b 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -674,6 +674,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(uint value) { AutoComplete(JsonToken.Integer); @@ -692,6 +693,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(ulong value) { AutoComplete(JsonToken.Integer); @@ -737,6 +739,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(ushort value) { AutoComplete(JsonToken.Integer); @@ -764,6 +767,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(sbyte value) { AutoComplete(JsonToken.Integer); @@ -814,6 +818,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(uint? value) { if (value == null) @@ -838,6 +843,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(ulong? value) { if (value == null) @@ -898,6 +904,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(ushort? value) { if (value == null) @@ -934,6 +941,7 @@ namespace Newtonsoft.Json /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public virtual void WriteValue(sbyte? value) { if (value == null) diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index d6f75517..b5e995dd 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -236,7 +236,7 @@ namespace Newtonsoft.Json.Linq return new JEnumerable(ChildrenInternal()); } - private IEnumerable ChildrenInternal() + internal IEnumerable ChildrenInternal() { JToken first = First; JToken current = first; diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 72cac7c2..b591adeb 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -315,7 +315,7 @@ namespace Newtonsoft.Json.Linq { writer.WriteStartObject(); - foreach (JProperty property in Properties()) + foreach (JProperty property in ChildrenInternal()) { property.WriteTo(writer, converters); } diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 3d6a027c..ea88bbc1 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -645,6 +645,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. /// The result of the conversion. + [CLSCompliant(false)] public static explicit operator uint?(JToken value) { if (value == null) @@ -662,6 +663,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. /// The result of the conversion. + [CLSCompliant(false)] public static explicit operator ulong?(JToken value) { if (value == null) @@ -724,6 +726,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. /// The result of the conversion. + [CLSCompliant(false)] public static explicit operator uint(JToken value) { JValue v = EnsureValue(value); @@ -738,6 +741,7 @@ namespace Newtonsoft.Json.Linq /// /// The value. /// The result of the conversion. + [CLSCompliant(false)] public static explicit operator ulong(JToken value) { JValue v = EnsureValue(value); @@ -852,6 +856,7 @@ namespace Newtonsoft.Json.Linq /// /// The value to create a from. /// The initialized with the specified value. + [CLSCompliant(false)] public static implicit operator JToken(ushort value) { return new JValue(value); @@ -922,6 +927,7 @@ namespace Newtonsoft.Json.Linq /// /// The value to create a from. /// The initialized with the specified value. + [CLSCompliant(false)] public static implicit operator JToken(ushort? value) { return new JValue(value); @@ -932,6 +938,7 @@ namespace Newtonsoft.Json.Linq /// /// The value to create a from. /// The initialized with the specified value. + [CLSCompliant(false)] public static implicit operator JToken(uint? value) { return new JValue(value); @@ -942,6 +949,7 @@ namespace Newtonsoft.Json.Linq /// /// The value to create a from. /// The initialized with the specified value. + [CLSCompliant(false)] public static implicit operator JToken(ulong? value) { return new JValue(value); @@ -982,6 +990,7 @@ namespace Newtonsoft.Json.Linq /// /// The value to create a from. /// The initialized with the specified value. + [CLSCompliant(false)] public static implicit operator JToken(uint value) { return new JValue(value); @@ -992,6 +1001,7 @@ namespace Newtonsoft.Json.Linq /// /// The value to create a from. /// The initialized with the specified value. + [CLSCompliant(false)] public static implicit operator JToken(ulong value) { return new JValue(value); diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index a8258c34..ecb208d8 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -217,6 +217,7 @@ namespace Newtonsoft.Json.Linq /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(uint value) { base.WriteValue(value); @@ -237,6 +238,7 @@ namespace Newtonsoft.Json.Linq /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(ulong value) { base.WriteValue(value); @@ -287,6 +289,7 @@ namespace Newtonsoft.Json.Linq /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); @@ -317,6 +320,7 @@ namespace Newtonsoft.Json.Linq /// Writes a value. /// /// The value to write. + [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 79d8155a..293749f4 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -68,6 +68,7 @@ namespace Newtonsoft.Json.Linq /// Initializes a new instance of the class with the given value. /// /// The value. + [CLSCompliant(false)] public JValue(ulong value) : this(value, JTokenType.Integer) { @@ -271,16 +272,6 @@ namespace Newtonsoft.Json.Linq } } - private static void WriteConvertableValue(JsonWriter writer, IList converters, Action defaultWrite, object value) - { - JsonConverter matchingConverter; - - if (value != null && ((matchingConverter = JsonSerializer.GetMatchingConverter(converters, value.GetType())) != null)) - matchingConverter.WriteJson(writer, value, new JsonSerializer()); - else - defaultWrite(value); - } - /// /// Writes this token to a . /// @@ -292,45 +283,53 @@ namespace Newtonsoft.Json.Linq { case JTokenType.Comment: writer.WriteComment(_value.ToString()); - break; - case JTokenType.Integer: - WriteConvertableValue(writer, converters, v => writer.WriteValue(Convert.ToInt64(v, CultureInfo.InvariantCulture)), _value); - break; - case JTokenType.Float: - WriteConvertableValue(writer, converters, v => writer.WriteValue(Convert.ToDouble(v, CultureInfo.InvariantCulture)), _value); - break; - case JTokenType.String: - WriteConvertableValue(writer, converters, v => writer.WriteValue((v != null) ? v.ToString() : null), _value); - break; - case JTokenType.Boolean: - WriteConvertableValue(writer, converters, v => writer.WriteValue(Convert.ToBoolean(v, CultureInfo.InvariantCulture)), _value); - break; - case JTokenType.Date: - WriteConvertableValue(writer, converters, v => - { -#if !PocketPC && !NET20 - if (v is DateTimeOffset) - writer.WriteValue((DateTimeOffset)v); - else -#endif - writer.WriteValue(Convert.ToDateTime(v, CultureInfo.InvariantCulture)); - }, _value); - break; + return; case JTokenType.Raw: writer.WriteRawValue((_value != null) ? _value.ToString() : null); - break; - case JTokenType.Bytes: - WriteConvertableValue(writer, converters, v => writer.WriteValue((byte[])v), _value); - break; + return; case JTokenType.Null: writer.WriteNull(); - break; + return; case JTokenType.Undefined: writer.WriteUndefined(); - break; - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", _valueType, "Unexpected token type."); + return; } + + JsonConverter matchingConverter; + if (_value != null && ((matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType())) != null)) + { + matchingConverter.WriteJson(writer, _value, new JsonSerializer()); + return; + } + + switch (_valueType) + { + case JTokenType.Integer: + writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture)); + return; + case JTokenType.Float: + writer.WriteValue(Convert.ToDouble(_value, CultureInfo.InvariantCulture)); + return; + case JTokenType.String: + writer.WriteValue((_value != null) ? _value.ToString() : null); + return; + case JTokenType.Boolean: + writer.WriteValue(Convert.ToBoolean(_value, CultureInfo.InvariantCulture)); + return; + case JTokenType.Date: +#if !PocketPC && !NET20 + if (_value is DateTimeOffset) + writer.WriteValue((DateTimeOffset)_value); + else +#endif + writer.WriteValue(Convert.ToDateTime(_value, CultureInfo.InvariantCulture)); ; + return; + case JTokenType.Bytes: + writer.WriteValue((byte[])_value); + return; + } + + throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", _valueType, "Unexpected token type."); } internal override int GetDeepHashCode() diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 1659d483..ee62b13d 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -17,6 +17,7 @@ // * Any of these conditions can be waived if you get permission from the copyright holder. #endregion +using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -97,4 +98,6 @@ using System.Security; [assembly: AssemblyVersion("3.5.0.0")] #if !PocketPC [assembly: AssemblyFileVersion("3.5.0.0")] -#endif \ No newline at end of file +#endif + +[assembly: CLSCompliant(true)] \ No newline at end of file