From f5fec30c2a88265d52c073393b009bfaf01c3500 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 11 Aug 2012 20:12:49 +1200 Subject: [PATCH] -Fixed error when writing JSON for a JProperty with no value -LINQ to JSON performance improvements --- .../Linq/JObjectTests.cs | 15 ++++- Src/Newtonsoft.Json/Linq/JArray.cs | 2 +- Src/Newtonsoft.Json/Linq/JContainer.cs | 60 ++++++++++++++----- Src/Newtonsoft.Json/Linq/JObject.cs | 14 +++-- Src/Newtonsoft.Json/Linq/JProperty.cs | 11 +++- Src/Newtonsoft.Json/Linq/JValue.cs | 5 +- 6 files changed, 78 insertions(+), 29 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index 9913f031..7ff6f612 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -52,6 +52,17 @@ namespace Newtonsoft.Json.Tests.Linq [TestFixture] public class JObjectTests : TestFixtureBase { + [Test] + public void WritePropertyWithNoValue() + { + var o = new JObject(); + o.Add(new JProperty("novalue")); + + Assert.AreEqual(@"{ + ""novalue"": null +}", o.ToString()); + } + [Test] public void Keys() { @@ -1360,7 +1371,7 @@ Parameter name: arrayIndex", public void IBindingListAddNewWithEvent() { JObject o = new JObject(); - o.AddingNew += (s, e) => e.NewObject = new JProperty("Property!"); + o._addingNew += (s, e) => e.NewObject = new JProperty("Property!"); IBindingList l = o; object newObject = l.AddNew(); @@ -1441,7 +1452,7 @@ Parameter name: arrayIndex", NotifyCollectionChangedAction? changedType = null; int? index = null; - o.CollectionChanged += (s, a) => + o._collectionChanged += (s, a) => { changedType = a.Action; index = a.NewStartingIndex; diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs index d91254f4..8c34688e 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.cs @@ -188,7 +188,7 @@ namespace Newtonsoft.Json.Linq { writer.WriteStartArray(); - foreach (JToken token in ChildrenTokens) + foreach (JToken token in _values) { token.WriteTo(writer, converters); } diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index f106e855..157ea283 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -56,21 +56,37 @@ namespace Newtonsoft.Json.Linq #endif { #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) + internal ListChangedEventHandler _listChanged; + internal AddingNewEventHandler _addingNew; + internal NotifyCollectionChangedEventHandler _collectionChanged; + /// /// Occurs when the list changes or an item in the list changes. /// - public event ListChangedEventHandler ListChanged; + public event ListChangedEventHandler ListChanged + { + add { _listChanged += value; } + remove { _listChanged -= value; } + } /// /// Occurs before an item is added to the collection. /// - public event AddingNewEventHandler AddingNew; + public event AddingNewEventHandler AddingNew + { + add { _addingNew += value; } + remove { _addingNew -= value; } + } #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) /// /// Occurs when the items list of the collection has changed, or the collection is reset. /// - public event NotifyCollectionChangedEventHandler CollectionChanged; + public event NotifyCollectionChangedEventHandler CollectionChanged + { + add { _collectionChanged += value; } + remove { _collectionChanged -= value; } + } #endif /// @@ -87,6 +103,7 @@ namespace Newtonsoft.Json.Linq } internal JContainer(JContainer other) + : this() { ValidationUtils.ArgumentNotNull(other, "c"); @@ -102,14 +119,19 @@ namespace Newtonsoft.Json.Linq throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType())); } + internal virtual IList CreateChildrenCollection() + { + return new List(); + } + #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) /// - /// Raises the event. + /// Raises the event. /// /// The instance containing the event data. protected virtual void OnAddingNew(AddingNewEventArgs e) { - AddingNewEventHandler handler = AddingNew; + AddingNewEventHandler handler = _addingNew; if (handler != null) handler(this, e); } @@ -120,7 +142,7 @@ namespace Newtonsoft.Json.Linq /// The instance containing the event data. protected virtual void OnListChanged(ListChangedEventArgs e) { - ListChangedEventHandler handler = ListChanged; + ListChangedEventHandler handler = _listChanged; if (handler != null) { @@ -138,12 +160,12 @@ namespace Newtonsoft.Json.Linq #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) /// - /// Raises the event. + /// Raises the event. /// /// The instance containing the event data. protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { - NotifyCollectionChangedEventHandler handler = CollectionChanged; + NotifyCollectionChangedEventHandler handler = _collectionChanged; if (handler != null) { @@ -330,11 +352,11 @@ namespace Newtonsoft.Json.Linq ChildrenTokens.Insert(index, item); #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - if (ListChanged != null) + if (_listChanged != null) OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index)); #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) - if (CollectionChanged != null) + if (_collectionChanged != null) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); #endif } @@ -364,10 +386,12 @@ namespace Newtonsoft.Json.Linq ChildrenTokens.RemoveAt(index); #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); + if (_listChanged != null) + OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); + if (_collectionChanged != null) + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); #endif } @@ -426,10 +450,12 @@ namespace Newtonsoft.Json.Linq existing.Next = null; #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); + if (_listChanged != null) + OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index)); + if (_collectionChanged != null) + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index)); #endif } @@ -447,10 +473,12 @@ namespace Newtonsoft.Json.Linq ChildrenTokens.Clear(); #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); + if (_listChanged != null) + OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + if (_collectionChanged != null) + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); #endif } diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 9c427079..6fe911f2 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -159,10 +159,12 @@ namespace Newtonsoft.Json.Linq { OnPropertyChanged(childProperty.Name); #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty))); + if (_listChanged != null) + OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty))); #endif #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE) - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty))); + if (_collectionChanged != null) + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty))); #endif } @@ -193,7 +195,7 @@ namespace Newtonsoft.Json.Linq /// An of this object's properties. public IEnumerable Properties() { - return ChildrenTokens.Cast(); + return _properties.Cast(); } /// @@ -368,7 +370,7 @@ namespace Newtonsoft.Json.Linq { writer.WriteStartObject(); - foreach (JProperty property in ChildrenTokens) + foreach (JProperty property in _properties) { property.WriteTo(writer, converters); } @@ -476,7 +478,7 @@ namespace Newtonsoft.Json.Linq throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); int index = 0; - foreach (JProperty property in ChildrenTokens) + foreach (JProperty property in _properties) { array[arrayIndex + index] = new KeyValuePair(property.Name, property.Value); index++; @@ -512,7 +514,7 @@ namespace Newtonsoft.Json.Linq /// public IEnumerator> GetEnumerator() { - foreach (JProperty property in ChildrenTokens) + foreach (JProperty property in _properties) { yield return new KeyValuePair(property.Name, property.Value); } diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs index ccfba603..3c187bf4 100644 --- a/Src/Newtonsoft.Json/Linq/JProperty.cs +++ b/Src/Newtonsoft.Json/Linq/JProperty.cs @@ -65,14 +65,14 @@ namespace Newtonsoft.Json.Linq public JToken Value { [DebuggerStepThrough] - get { return (ChildrenTokens.Count > 0) ? ChildrenTokens[0] : null; } + get { return (_content.Count > 0) ? _content[0] : null; } set { CheckReentrancy(); JToken newValue = value ?? new JValue((object) null); - if (ChildrenTokens.Count == 0) + if (_content.Count == 0) { InsertItem(0, newValue, false); } @@ -209,7 +209,12 @@ namespace Newtonsoft.Json.Linq public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WritePropertyName(_name); - Value.WriteTo(writer, converters); + + JToken value = Value; + if (value != null) + value.WriteTo(writer, converters); + else + writer.WriteNull(); } internal override int GetDeepHashCode() diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index a164cd42..88a7dd04 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -528,7 +528,10 @@ namespace Newtonsoft.Json.Linq } JsonConverter matchingConverter; - if (_value != null && ((matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType())) != null)) + if (_value != null + && converters != null + && converters.Length > 0 + && ((matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType())) != null)) { matchingConverter.WriteJson(writer, _value, new JsonSerializer()); return;