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
diff options
context:
space:
mode:
authorJames Newton-King <james@newtonking.com>2012-03-07 13:08:06 +0400
committerJames Newton-King <james@newtonking.com>2012-03-07 13:08:06 +0400
commitc7f52087690ea8e54e52366f1be2506cb313e45e (patch)
tree6df396f58fabda9d29bf071888184abc9556222a
parentf8a13d7aa3bdcf9b42e253962b377c1b989cf2a3 (diff)
-Added async serialize/deserialize methods to JsonConvert
-Fixed performance issue when deserializing deeply nested JSON to LINQ to JSON objects
-rw-r--r--Src/Newtonsoft.Json.Tests/JsonConvertTest.cs80
-rw-r--r--Src/Newtonsoft.Json.Tests/PerformanceTests.cs34
-rw-r--r--Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs2
-rw-r--r--Src/Newtonsoft.Json/JsonConvert.cs130
-rw-r--r--Src/Newtonsoft.Json/JsonTextReader.cs6
-rw-r--r--Src/Newtonsoft.Json/Linq/JArray.cs2
-rw-r--r--Src/Newtonsoft.Json/Linq/JContainer.cs45
-rw-r--r--Src/Newtonsoft.Json/Linq/JObject.cs4
-rw-r--r--Src/Newtonsoft.Json/Linq/JProperty.cs6
-rw-r--r--Src/Newtonsoft.Json/Linq/JToken.cs4
-rw-r--r--Src/Newtonsoft.Json/Linq/JTokenWriter.cs2
-rw-r--r--Src/Newtonsoft.Json/Properties/AssemblyInfo.cs2
12 files changed, 265 insertions, 52 deletions
diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
index f1348c2..01bfb47 100644
--- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs
@@ -24,11 +24,18 @@
#endregion
using System;
+using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
+#if !(NET20 || NET35 || SILVERLIGHT)
+using System.Threading.Tasks;
+#endif
using System.Xml;
using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Tests.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
using Newtonsoft.Json.Utilities;
using NUnit.Framework;
@@ -640,5 +647,78 @@ now brown cow?", '"', true);
return (T)converter.ReadJson(reader, typeof(T), null, null);
}
+
+#if !(NET20 || NET35 || SILVERLIGHT)
+ [Test]
+ public void Async()
+ {
+ Task<string> task = null;
+
+ task = JsonConvert.SerializeObjectAsync(42);
+ task.Wait();
+
+ Assert.AreEqual("42", task.Result);
+
+ task = JsonConvert.SerializeObjectAsync(new[] {1, 2, 3, 4, 5}, Formatting.Indented);
+ task.Wait();
+
+ Assert.AreEqual(@"[
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+]", task.Result);
+
+ task = JsonConvert.SerializeObjectAsync(DateTime.MaxValue, Formatting.None, new JsonSerializerSettings
+ {
+ DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
+ });
+ task.Wait();
+
+ Assert.AreEqual(@"""\/Date(253402300799999)\/""", task.Result);
+
+ var taskObject = JsonConvert.DeserializeObjectAsync("[]");
+ taskObject.Wait();
+
+ Assert.AreEqual(new JArray(), taskObject.Result);
+
+ Task<object> taskVersionArray = JsonConvert.DeserializeObjectAsync("['2.0']", typeof(Version[]), new JsonSerializerSettings
+ {
+ Converters = {new VersionConverter()}
+ });
+ taskVersionArray.Wait();
+
+ Version[] versionArray = (Version[])taskVersionArray.Result;
+
+ Assert.AreEqual(1, versionArray.Length);
+ Assert.AreEqual(2, versionArray[0].Major);
+
+ Task<int> taskInt = JsonConvert.DeserializeObjectAsync<int>("5");
+ taskInt.Wait();
+
+ Assert.AreEqual(5, taskInt.Result);
+
+ var taskVersion = JsonConvert.DeserializeObjectAsync<Version>("'2.0'", new JsonSerializerSettings
+ {
+ Converters = {new VersionConverter()}
+ });
+ taskVersion.Wait();
+
+ Assert.AreEqual(2, taskVersion.Result.Major);
+
+ Movie p = new Movie();
+ p.Name = "Existing,";
+
+ Task taskVoid = JsonConvert.PopulateObjectAsync("{'Name':'Appended'}", p, new JsonSerializerSettings
+ {
+ Converters = new List<JsonConverter> { new JsonSerializerTest.StringAppenderConverter() }
+ });
+
+ taskVoid.Wait();
+
+ Assert.AreEqual("Existing,Appended", p.Name);
+ }
+#endif
}
} \ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
index ca92859..57c9e8e 100644
--- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
+++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
@@ -704,7 +704,6 @@ namespace Newtonsoft.Json.Tests
}
[Test]
- [Ignore]
public void NestedJToken()
{
Stopwatch sw;
@@ -717,7 +716,7 @@ namespace Newtonsoft.Json.Tests
for (int j = 0; j < i; j++)
{
JArray temp = new JArray();
- ija.Add(temp);
+ ija.AddAndSkipParentCheck(temp);
ija = temp;
}
ija.Add(1);
@@ -727,26 +726,21 @@ namespace Newtonsoft.Json.Tests
}
[Test]
- [Ignore]
- public void NestedXElement()
+ public void DeserializeNestedJToken()
{
+ string json = (new string('[', 100000)) + "1" + ((new string(']', 100000)));
+
Stopwatch sw;
- for (int i = 10000; i <= 100000; i += 10000)
- {
- sw = new Stopwatch();
- sw.Start();
- XElement ija = new XElement("root");
- XElement ijt = ija;
- for (int j = 0; j < i; j++)
- {
- XElement temp = new XElement("child");
- ija.Add(temp);
- ija = temp;
- }
- ija.Add(1);
- sw.Stop();
- Console.WriteLine("Created a XElement of depth {0} (using OM) in {1} millis", i, sw.ElapsedMilliseconds);
- }
+ sw = new Stopwatch();
+ sw.Start();
+
+ var a = (JArray)JsonConvert.DeserializeObject(json);
+
+ sw.Stop();
+
+ Assert.AreEqual(1, a.Count);
+
+ Console.WriteLine("Deserialize big ass nested array in {0} millis", sw.ElapsedMilliseconds);
}
}
diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
index e5c19f6..7920d37 100644
--- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
@@ -72,5 +72,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.8.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.0.8.14704")]
+[assembly: AssemblyFileVersion("4.0.8.14707")]
#endif
diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs
index 5682f8e..33689de 100644
--- a/Src/Newtonsoft.Json/JsonConvert.cs
+++ b/Src/Newtonsoft.Json/JsonConvert.cs
@@ -26,6 +26,9 @@
using System;
using System.IO;
using System.Globalization;
+#if !(NET20 || NET35 || SILVERLIGHT)
+using System.Threading.Tasks;
+#endif
using Newtonsoft.Json.Utilities;
using System.Xml;
using Newtonsoft.Json.Converters;
@@ -643,6 +646,7 @@ namespace Newtonsoft.Json
return IsJsonPrimitiveTypeCode(Type.GetTypeCode(type));
}
+ #region Serialize
/// <summary>
/// Serializes the specified object to a JSON string.
/// </summary>
@@ -733,6 +737,50 @@ namespace Newtonsoft.Json
return sw.ToString();
}
+#if !(NET20 || NET35 || SILVERLIGHT)
+ /// <summary>
+ /// Asynchronously serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
+ /// </summary>
+ /// <param name="value">The object to serialize.</param>
+ /// <returns>
+ /// A task that represents the asynchronous serialize operation. The value of the <c>TResult</c> parameter contains a JSON string representation of the object.
+ /// </returns>
+ public static Task<string> SerializeObjectAsync(object value)
+ {
+ return SerializeObjectAsync(value, Formatting.None, null);
+ }
+
+ /// <summary>
+ /// Asynchronously serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
+ /// </summary>
+ /// <param name="value">The object to serialize.</param>
+ /// <param name="formatting">Indicates how the output is formatted.</param>
+ /// <returns>
+ /// A task that represents the asynchronous serialize operation. The value of the <c>TResult</c> parameter contains a JSON string representation of the object.
+ /// </returns>
+ public static Task<string> SerializeObjectAsync(object value, Formatting formatting)
+ {
+ return SerializeObjectAsync(value, formatting, null);
+ }
+
+ /// <summary>
+ /// Asynchronously serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
+ /// </summary>
+ /// <param name="value">The object to serialize.</param>
+ /// <param name="formatting">Indicates how the output is formatted.</param>
+ /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
+ /// If this is null, default serialization settings will be is used.</param>
+ /// <returns>
+ /// A task that represents the asynchronous serialize operation. The value of the <c>TResult</c> parameter contains a JSON string representation of the object.
+ /// </returns>
+ public static Task<string> SerializeObjectAsync(object value, Formatting formatting, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => SerializeObject(value, formatting, settings));
+ }
+#endif
+ #endregion
+
+ #region Deserialize
/// <summary>
/// Deserializes the JSON to a .NET object.
/// </summary>
@@ -868,6 +916,68 @@ namespace Newtonsoft.Json
return deserializedValue;
}
+#if !(NET20 || NET35 || SILVERLIGHT)
+ /// <summary>
+ /// Asynchronously deserializes the JSON to the specified .NET type.
+ /// </summary>
+ /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+ /// <param name="value">The JSON to deserialize.</param>
+ /// <returns>
+ /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+ /// </returns>
+ public static Task<T> DeserializeObjectAsync<T>(string value)
+ {
+ return DeserializeObjectAsync<T>(value, null);
+ }
+
+ /// <summary>
+ /// Asynchronously deserializes the JSON to the specified .NET type.
+ /// </summary>
+ /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+ /// <param name="value">The JSON to deserialize.</param>
+ /// <param name="settings">
+ /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+ /// If this is null, default serialization settings will be is used.
+ /// </param>
+ /// <returns>
+ /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+ /// </returns>
+ public static Task<T> DeserializeObjectAsync<T>(string value, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => DeserializeObject<T>(value, settings));
+ }
+
+ /// <summary>
+ /// Asynchronously deserializes the JSON to the specified .NET type.
+ /// </summary>
+ /// <param name="value">The JSON to deserialize.</param>
+ /// <returns>
+ /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+ /// </returns>
+ public static Task<object> DeserializeObjectAsync(string value)
+ {
+ return DeserializeObjectAsync(value, null, null);
+ }
+
+ /// <summary>
+ /// Asynchronously deserializes the JSON to the specified .NET type.
+ /// </summary>
+ /// <param name="value">The JSON to deserialize.</param>
+ /// <param name="type">The type of the object to deserialize to.</param>
+ /// <param name="settings">
+ /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+ /// If this is null, default serialization settings will be is used.
+ /// </param>
+ /// <returns>
+ /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+ /// </returns>
+ public static Task<object> DeserializeObjectAsync(string value, Type type, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => DeserializeObject(value, type, settings));
+ }
+#endif
+ #endregion
+
/// <summary>
/// Populates the object with values from the JSON string.
/// </summary>
@@ -878,7 +988,6 @@ namespace Newtonsoft.Json
PopulateObject(value, target, null);
}
-
/// <summary>
/// Populates the object with values from the JSON string.
/// </summary>
@@ -902,6 +1011,25 @@ namespace Newtonsoft.Json
}
}
+#if !(NET20 || NET35 || SILVERLIGHT)
+ /// <summary>
+ /// Asynchronously populates the object with values from the JSON string.
+ /// </summary>
+ /// <param name="value">The JSON to populate values from.</param>
+ /// <param name="target">The target object to populate values onto.</param>
+ /// <param name="settings">
+ /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+ /// If this is null, default serialization settings will be is used.
+ /// </param>
+ /// <returns>
+ /// A task that represents the asynchronous populate operation.
+ /// </returns>
+ public static Task PopulateObjectAsync(string value, object target, JsonSerializerSettings settings)
+ {
+ return Task.Factory.StartNew(() => PopulateObject(value, target, settings));
+ }
+#endif
+
#if !SILVERLIGHT
/// <summary>
/// Serializes the XML node to a JSON string.
diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs
index f409175..c7ffa80 100644
--- a/Src/Newtonsoft.Json/JsonTextReader.cs
+++ b/Src/Newtonsoft.Json/JsonTextReader.cs
@@ -159,11 +159,13 @@ namespace Newtonsoft.Json
private bool ParseDateIso(string text)
{
+ const string isoDateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK";
+
#if !NET20
if (_readType == ReadType.ReadAsDateTimeOffset)
{
DateTimeOffset dateTimeOffset;
- if (DateTimeOffset.TryParseExact(text, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTimeOffset))
+ if (DateTimeOffset.TryParseExact(text, isoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTimeOffset))
{
SetToken(JsonToken.Date, dateTimeOffset);
return true;
@@ -173,7 +175,7 @@ namespace Newtonsoft.Json
#endif
{
DateTime dateTime;
- if (DateTime.TryParseExact(text, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTime))
+ if (DateTime.TryParseExact(text, isoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTime))
{
dateTime = JsonConvert.EnsureDateTime(dateTime, DateTimeZoneHandling);
diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs
index 3705a8d..da7d2a0 100644
--- a/Src/Newtonsoft.Json/Linq/JArray.cs
+++ b/Src/Newtonsoft.Json/Linq/JArray.cs
@@ -247,7 +247,7 @@ namespace Newtonsoft.Json.Linq
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
public void Insert(int index, JToken item)
{
- InsertItem(index, item);
+ InsertItem(index, item, false);
}
/// <summary>
diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs
index 01bda6e..d1f83e0 100644
--- a/Src/Newtonsoft.Json/Linq/JContainer.cs
+++ b/Src/Newtonsoft.Json/Linq/JContainer.cs
@@ -261,7 +261,7 @@ namespace Newtonsoft.Json.Linq
return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]));
}
- internal JToken EnsureParentToken(JToken item)
+ internal JToken EnsureParentToken(JToken item, bool skipParentCheck)
{
if (item == null)
return new JValue((object) null);
@@ -273,14 +273,18 @@ namespace Newtonsoft.Json.Linq
else
{
// check whether attempting to add a token to itself
- JContainer parent = this;
- while (parent.Parent != null)
+ // not possible with a value, only a container
+ if (item is JContainer && !skipParentCheck)
{
- parent = parent.Parent;
- }
- if (item == parent)
- {
- item = item.CloneToken();
+ JContainer parent = this;
+ while (parent.Parent != null)
+ {
+ parent = parent.Parent;
+ }
+ if (item == parent)
+ {
+ item = item.CloneToken();
+ }
}
}
return item;
@@ -309,14 +313,14 @@ namespace Newtonsoft.Json.Linq
return ChildrenTokens.IndexOf(item, JTokenReferenceEqualityComparer.Instance);
}
- internal virtual void InsertItem(int index, JToken item)
+ internal virtual void InsertItem(int index, JToken item, bool skipParentCheck)
{
if (index > ChildrenTokens.Count)
throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List.");
CheckReentrancy();
- item = EnsureParentToken(item);
+ item = EnsureParentToken(item, skipParentCheck);
JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
// haven't inserted new token yet so next token is still at the inserting index
@@ -409,7 +413,7 @@ namespace Newtonsoft.Json.Linq
CheckReentrancy();
- item = EnsureParentToken(item);
+ item = EnsureParentToken(item, false);
ValidateToken(item, existing);
@@ -523,7 +527,12 @@ namespace Newtonsoft.Json.Linq
/// <param name="content">The content to be added.</param>
public virtual void Add(object content)
{
- AddInternal(ChildrenTokens.Count, content);
+ AddInternal(ChildrenTokens.Count, content, false);
+ }
+
+ internal void AddAndSkipParentCheck(JToken token)
+ {
+ AddInternal(ChildrenTokens.Count, token, true);
}
/// <summary>
@@ -532,10 +541,10 @@ namespace Newtonsoft.Json.Linq
/// <param name="content">The content to be added.</param>
public void AddFirst(object content)
{
- AddInternal(0, content);
+ AddInternal(0, content, false);
}
- internal void AddInternal(int index, object content)
+ internal void AddInternal(int index, object content, bool skipParentCheck)
{
if (IsMultiContent(content))
{
@@ -544,7 +553,7 @@ namespace Newtonsoft.Json.Linq
int multiIndex = index;
foreach (object c in enumerable)
{
- AddInternal(multiIndex, c);
+ AddInternal(multiIndex, c, skipParentCheck);
multiIndex++;
}
}
@@ -552,7 +561,7 @@ namespace Newtonsoft.Json.Linq
{
JToken item = CreateFromContent(content);
- InsertItem(index, item);
+ InsertItem(index, item, skipParentCheck);
}
}
@@ -745,7 +754,7 @@ namespace Newtonsoft.Json.Linq
void IList<JToken>.Insert(int index, JToken item)
{
- InsertItem(index, item);
+ InsertItem(index, item, false);
}
void IList<JToken>.RemoveAt(int index)
@@ -831,7 +840,7 @@ namespace Newtonsoft.Json.Linq
void IList.Insert(int index, object value)
{
- InsertItem(index, EnsureValue(value));
+ InsertItem(index, EnsureValue(value), false);
}
bool IList.IsFixedSize
diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs
index 0478d2c..13ca2fd 100644
--- a/Src/Newtonsoft.Json/Linq/JObject.cs
+++ b/Src/Newtonsoft.Json/Linq/JObject.cs
@@ -146,13 +146,13 @@ namespace Newtonsoft.Json.Linq
return (t != null && ContentsEqual(t));
}
- internal override void InsertItem(int index, JToken item)
+ internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
// don't add comments to JObject, no name to reference comment by
if (item != null && item.Type == JTokenType.Comment)
return;
- base.InsertItem(index, item);
+ base.InsertItem(index, item, skipParentCheck);
}
internal override void ValidateToken(JToken o, JToken existing)
diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs
index 3487ab1..4456818 100644
--- a/Src/Newtonsoft.Json/Linq/JProperty.cs
+++ b/Src/Newtonsoft.Json/Linq/JProperty.cs
@@ -78,7 +78,7 @@ namespace Newtonsoft.Json.Linq
if (ChildrenTokens.Count == 0)
{
- InsertItem(0, newValue);
+ InsertItem(0, newValue, false);
}
else
{
@@ -132,12 +132,12 @@ namespace Newtonsoft.Json.Linq
throw new Exception("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
- internal override void InsertItem(int index, JToken item)
+ internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
if (Value != null)
throw new Exception("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
- base.InsertItem(0, item);
+ base.InsertItem(0, item, false);
}
internal override bool ContainsItem(JToken item)
diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs
index 019fbc1..15cb4a9 100644
--- a/Src/Newtonsoft.Json/Linq/JToken.cs
+++ b/Src/Newtonsoft.Json/Linq/JToken.cs
@@ -167,7 +167,7 @@ namespace Newtonsoft.Json.Linq
throw new InvalidOperationException("The parent is missing.");
int index = _parent.IndexOfItem(this);
- _parent.AddInternal(index + 1, content);
+ _parent.AddInternal(index + 1, content, false);
}
/// <summary>
@@ -180,7 +180,7 @@ namespace Newtonsoft.Json.Linq
throw new InvalidOperationException("The parent is missing.");
int index = _parent.IndexOfItem(this);
- _parent.AddInternal(index, content);
+ _parent.AddInternal(index, content, false);
}
/// <summary>
diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs
index d587539..ccc02b8 100644
--- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs
+++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs
@@ -81,7 +81,7 @@ namespace Newtonsoft.Json.Linq
if (_parent == null)
_token = container;
else
- _parent.Add(container);
+ _parent.AddAndSkipParentCheck(container);
_parent = container;
}
diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
index 32ff8a2..73df4a0 100644
--- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
@@ -85,7 +85,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.8.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.0.8.14704")]
+[assembly: AssemblyFileVersion("4.0.8.14707")]
#endif
[assembly: CLSCompliant(true)]