-Added WriteValue(object) to JsonWriter

-Added JTokenEqualityComparer
-Added additional validation to new IDictionary/ICollection methods on JObject/JArray
-Changed JObject so that properties must have a unique name
-Changed remaining IConvertible calls to use ToXXX methods instead of casting
-Fixed many bugs in new IDictionary/ICollection methods on JObject/JArray
-Fixed AddFirst when no existing children
This commit is contained in:
JamesNK
2008-08-12 11:13:27 +00:00
parent 12ca14261c
commit f9772626b8
22 changed files with 925 additions and 102 deletions
@@ -148,6 +148,9 @@
<Compile Include="..\Newtonsoft.Json\Linq\JToken.cs">
<Link>Linq\JToken.cs</Link>
</Compile>
<Compile Include="..\Newtonsoft.Json\Linq\JTokenEqualityComparer.cs">
<Link>Linq\JTokenEqualityComparer.cs</Link>
</Compile>
<Compile Include="..\Newtonsoft.Json\Linq\JValue.cs">
<Link>Linq\JValue.cs</Link>
</Compile>
@@ -90,6 +90,15 @@
<Compile Include="..\Newtonsoft.Json.Tests\JsonTokenWriterTest.cs">
<Link>JsonTokenWriterTest.cs</Link>
</Compile>
<Compile Include="..\Newtonsoft.Json.Tests\Linq\JArrayTests.cs">
<Link>Linq\JArrayTests.cs</Link>
</Compile>
<Compile Include="..\Newtonsoft.Json.Tests\Linq\JObjectTests.cs">
<Link>Linq\JObjectTests.cs</Link>
</Compile>
<Compile Include="..\Newtonsoft.Json.Tests\Linq\JTokenEqualityComparerTests.cs">
<Link>Linq\JTokenEqualityComparerTests.cs</Link>
</Compile>
<Compile Include="..\Newtonsoft.Json.Tests\Linq\JTokenTests.cs">
<Link>Linq\JTokenTests.cs</Link>
</Compile>
@@ -113,5 +113,65 @@ now brown cow?", '"', true);
string json = JavaScriptConvert.ToString(StringComparison.CurrentCultureIgnoreCase);
Assert.AreEqual("1", json);
}
[Test]
public void ObjectToString()
{
object value;
value = 1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = 1.1;
Assert.AreEqual("1.1", JavaScriptConvert.ToString(value));
value = 1.1m;
Assert.AreEqual("1.1", JavaScriptConvert.ToString(value));
value = (float)1.1;
Assert.AreEqual("1.1", JavaScriptConvert.ToString(value));
value = (short)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = (long)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = (byte)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = (uint)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = (ushort)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = (sbyte)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = (ulong)1;
Assert.AreEqual("1", JavaScriptConvert.ToString(value));
value = new DateTime(JavaScriptConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc);
Assert.AreEqual(@"""\/Date(0)\/""", JavaScriptConvert.ToString(value));
value = new DateTimeOffset(JavaScriptConvert.InitialJavaScriptDateTicks, TimeSpan.Zero);
Assert.AreEqual(@"""\/Date(0+0000)\/""", JavaScriptConvert.ToString(value));
value = null;
Assert.AreEqual("null", JavaScriptConvert.ToString(value));
value = DBNull.Value;
Assert.AreEqual("null", JavaScriptConvert.ToString(value));
value = "I am a string";
Assert.AreEqual(@"""I am a string""", JavaScriptConvert.ToString(value));
value = true;
Assert.AreEqual("true", JavaScriptConvert.ToString(value));
value = 'c';
Assert.AreEqual(@"""c""", JavaScriptConvert.ToString(value));
}
}
}
@@ -0,0 +1,294 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Linq
{
public class JArrayTests : TestFixtureBase
{
[Test]
public void Clear()
{
JArray a = new JArray { 1 };
Assert.AreEqual(1, a.Count);
a.Clear();
Assert.AreEqual(0, a.Count);
}
[Test]
public void Contains()
{
JValue v = new JValue(1);
JArray a = new JArray { v };
Assert.AreEqual(false, a.Contains(new JValue(2)));
Assert.AreEqual(false, a.Contains(new JValue(1)));
Assert.AreEqual(false, a.Contains(null));
Assert.AreEqual(true, a.Contains(v));
}
[Test]
public void GenericCollectionCopyTo()
{
JArray j = new JArray();
j.Add(new JValue(1));
j.Add(new JValue(2));
j.Add(new JValue(3));
Assert.AreEqual(3, j.Count);
JToken[] a = new JToken[5];
((ICollection<JToken>)j).CopyTo(a, 1);
Assert.AreEqual(null, a[0]);
Assert.AreEqual(1, (int)a[1]);
Assert.AreEqual(2, (int)a[2]);
Assert.AreEqual(3, (int)a[3]);
Assert.AreEqual(null, a[4]);
}
[Test]
[ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: array")]
public void GenericCollectionCopyToNullArrayShouldThrow()
{
JArray j = new JArray();
((ICollection<JToken>)j).CopyTo(null, 0);
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"arrayIndex is less than 0.
Parameter name: arrayIndex")]
public void GenericCollectionCopyToNegativeArrayIndexShouldThrow()
{
JArray j = new JArray();
((ICollection<JToken>)j).CopyTo(new JToken[1], -1);
}
[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"arrayIndex is equal to or greater than the length of array.")]
public void GenericCollectionCopyToArrayIndexEqualGreaterToArrayLengthShouldThrow()
{
JArray j = new JArray();
((ICollection<JToken>)j).CopyTo(new JToken[1], 1);
}
[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.")]
public void GenericCollectionCopyToInsufficientArrayCapacity()
{
JArray j = new JArray();
j.Add(new JValue(1));
j.Add(new JValue(2));
j.Add(new JValue(3));
((ICollection<JToken>)j).CopyTo(new JToken[3], 1);
}
[Test]
public void Remove()
{
JValue v = new JValue(1);
JArray j = new JArray();
j.Add(v);
Assert.AreEqual(1, j.Count);
Assert.AreEqual(false, j.Remove(new JValue(1)));
Assert.AreEqual(false, j.Remove(null));
Assert.AreEqual(true, j.Remove(v));
Assert.AreEqual(false, j.Remove(v));
Assert.AreEqual(0, j.Count);
}
[Test]
public void IndexOf()
{
JValue v1 = new JValue(1);
JValue v2 = new JValue(1);
JValue v3 = new JValue(1);
JArray j = new JArray();
j.Add(v1);
Assert.AreEqual(0, j.IndexOf(v1));
j.Add(v2);
Assert.AreEqual(0, j.IndexOf(v1));
Assert.AreEqual(1, j.IndexOf(v2));
j.AddFirst(v3);
Assert.AreEqual(1, j.IndexOf(v1));
Assert.AreEqual(2, j.IndexOf(v2));
Assert.AreEqual(0, j.IndexOf(v3));
v3.Remove();
Assert.AreEqual(0, j.IndexOf(v1));
Assert.AreEqual(1, j.IndexOf(v2));
Assert.AreEqual(-1, j.IndexOf(v3));
}
[Test]
public void RemoveAt()
{
JValue v1 = new JValue(1);
JValue v2 = new JValue(1);
JValue v3 = new JValue(1);
JArray j = new JArray();
j.Add(v1);
j.Add(v2);
j.Add(v3);
Assert.AreEqual(true, j.Contains(v1));
j.RemoveAt(0);
Assert.AreEqual(false, j.Contains(v1));
Assert.AreEqual(true, j.Contains(v3));
j.RemoveAt(1);
Assert.AreEqual(false, j.Contains(v3));
Assert.AreEqual(1, j.Count);
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"index is equal to or greater than Count.
Parameter name: index")]
public void RemoveAtOutOfRangeIndexShouldError()
{
JArray j = new JArray();
j.RemoveAt(0);
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"index is less than 0.
Parameter name: index")]
public void RemoveAtNegativeIndexShouldError()
{
JArray j = new JArray();
j.RemoveAt(-1);
}
[Test]
public void Insert()
{
JValue v1 = new JValue(1);
JValue v2 = new JValue(2);
JValue v3 = new JValue(3);
JValue v4 = new JValue(4);
JArray j = new JArray();
j.Add(v1);
j.Add(v2);
j.Add(v3);
j.Insert(1, v4);
Assert.AreEqual(0, j.IndexOf(v1));
Assert.AreEqual(1, j.IndexOf(v4));
Assert.AreEqual(2, j.IndexOf(v2));
Assert.AreEqual(3, j.IndexOf(v3));
}
[Test]
public void AddFirstAddedTokenShouldBeFirst()
{
JValue v1 = new JValue(1);
JValue v2 = new JValue(2);
JValue v3 = new JValue(3);
JArray j = new JArray();
Assert.AreEqual(null, j.First);
Assert.AreEqual(null, j.Last);
j.AddFirst(v1);
Assert.AreEqual(v1, j.First);
Assert.AreEqual(v1, j.Last);
j.AddFirst(v2);
Assert.AreEqual(v2, j.First);
Assert.AreEqual(v1, j.Last);
j.AddFirst(v3);
Assert.AreEqual(v3, j.First);
Assert.AreEqual(v1, j.Last);
}
[Test]
public void InsertShouldInsertAtZeroIndex()
{
JValue v1 = new JValue(1);
JValue v2 = new JValue(2);
JArray j = new JArray();
j.Insert(0, v1);
Assert.AreEqual(0, j.IndexOf(v1));
j.Insert(0, v2);
Assert.AreEqual(1, j.IndexOf(v1));
Assert.AreEqual(0, j.IndexOf(v2));
}
[Test]
public void InsertNull()
{
JArray j = new JArray();
j.Insert(0, null);
Assert.AreEqual(null, ((JValue)j[0]).Value);
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Specified argument was out of the range of valid values.
Parameter name: index")]
public void InsertNegativeIndexShouldThrow()
{
JArray j = new JArray();
j.Insert(-1, new JValue(1));
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Specified argument was out of the range of valid values.
Parameter name: index")]
public void InsertOutOfRangeIndexShouldThrow()
{
JArray j = new JArray();
j.Insert(2, new JValue(1));
}
[Test]
public void Item()
{
JValue v1 = new JValue(1);
JValue v2 = new JValue(2);
JValue v3 = new JValue(3);
JValue v4 = new JValue(4);
JArray j = new JArray();
j.Add(v1);
j.Add(v2);
j.Add(v3);
j[1] = v4;
Assert.AreEqual(null, v2.Parent);
Assert.AreEqual(-1, j.IndexOf(v2));
Assert.AreEqual(j, v4.Parent);
Assert.AreEqual(1, j.IndexOf(v4));
}
}
}
@@ -0,0 +1,233 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Linq
{
public class JObjectTests : TestFixtureBase
{
[Test]
public void TryGetValue()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
Assert.AreEqual(1, o.Children().Count());
JToken t;
Assert.AreEqual(false, o.TryGetValue("sdf", out t));
Assert.AreEqual(null, t);
Assert.AreEqual(false, o.TryGetValue(null, out t));
Assert.AreEqual(null, t);
Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
Assert.AreEqual(true, JToken.DeepEquals(new JValue(1), t));
}
[Test]
public void DictionaryItemShouldSet()
{
JObject o = new JObject();
o["PropertyNameValue"] = new JValue(1);
Assert.AreEqual(1, o.Children().Count());
JToken t;
Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
Assert.AreEqual(true, JToken.DeepEquals(new JValue(1), t));
o["PropertyNameValue"] = new JValue(2);
Assert.AreEqual(1, o.Children().Count());
Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
Assert.AreEqual(true, JToken.DeepEquals(new JValue(2), t));
o["PropertyNameValue"] = null;
Assert.AreEqual(1, o.Children().Count());
Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
Assert.AreEqual(true, JToken.DeepEquals(new JValue((object)null), t));
}
[Test]
public void Remove()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
Assert.AreEqual(1, o.Children().Count());
Assert.AreEqual(false, o.Remove("sdf"));
Assert.AreEqual(false, o.Remove(null));
Assert.AreEqual(true, o.Remove("PropertyNameValue"));
Assert.AreEqual(0, o.Children().Count());
}
[Test]
public void GenericCollectionRemove()
{
JValue v = new JValue(1);
JObject o = new JObject();
o.Add("PropertyNameValue", v);
Assert.AreEqual(1, o.Children().Count());
Assert.AreEqual(false, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue1", new JValue(1))));
Assert.AreEqual(false, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(2))));
Assert.AreEqual(false, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(1))));
Assert.AreEqual(true, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue", v)));
Assert.AreEqual(0, o.Children().Count());
}
[Test]
[ExpectedException(typeof(Exception), ExpectedMessage = "Can not add property PropertyNameValue to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.")]
public void DuplicatePropertyNameShouldThrow()
{
JObject o = new JObject();
o.Add("PropertyNameValue", null);
o.Add("PropertyNameValue", null);
}
[Test]
public void GenericDictionaryAdd()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
Assert.AreEqual(1, (int)o["PropertyNameValue"]);
o.Add("PropertyNameValue1", null);
Assert.AreEqual(null, ((JValue)o["PropertyNameValue1"]).Value);
Assert.AreEqual(2, o.Children().Count());
}
[Test]
public void GenericCollectionAdd()
{
JObject o = new JObject();
((ICollection<KeyValuePair<string,JToken>>)o).Add(new KeyValuePair<string,JToken>("PropertyNameValue", new JValue(1)));
Assert.AreEqual(1, (int)o["PropertyNameValue"]);
Assert.AreEqual(1, o.Children().Count());
}
[Test]
public void GenericCollectionClear()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
Assert.AreEqual(1, o.Children().Count());
JProperty p = (JProperty)o.Children().ElementAt(0);
((ICollection<KeyValuePair<string, JToken>>)o).Clear();
Assert.AreEqual(0, o.Children().Count());
Assert.AreEqual(null, p.Parent);
}
[Test]
public void GenericCollectionContains()
{
JValue v = new JValue(1);
JObject o = new JObject();
o.Add("PropertyNameValue", v);
Assert.AreEqual(1, o.Children().Count());
bool contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(1)));
Assert.AreEqual(false, contains);
contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue", v));
Assert.AreEqual(true, contains);
contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(2)));
Assert.AreEqual(false, contains);
contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue1", new JValue(1)));
Assert.AreEqual(false, contains);
contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(default(KeyValuePair<string, JToken>));
Assert.AreEqual(false, contains);
}
[Test]
public void GenericDictionaryContains()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
Assert.AreEqual(1, o.Children().Count());
bool contains = ((IDictionary<string, JToken>)o).ContainsKey("PropertyNameValue");
Assert.AreEqual(true, contains);
}
[Test]
public void GenericCollectionCopyTo()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
o.Add("PropertyNameValue2", new JValue(2));
o.Add("PropertyNameValue3", new JValue(3));
Assert.AreEqual(3, o.Children().Count());
KeyValuePair<string, JToken>[] a = new KeyValuePair<string,JToken>[5];
((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(a, 1);
Assert.AreEqual(default(KeyValuePair<string,JToken>), a[0]);
Assert.AreEqual("PropertyNameValue", a[1].Key);
Assert.AreEqual(1, (int)a[1].Value);
Assert.AreEqual("PropertyNameValue2", a[2].Key);
Assert.AreEqual(2, (int)a[2].Value);
Assert.AreEqual("PropertyNameValue3", a[3].Key);
Assert.AreEqual(3, (int)a[3].Value);
Assert.AreEqual(default(KeyValuePair<string, JToken>), a[4]);
}
[Test]
[ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: array")]
public void GenericCollectionCopyToNullArrayShouldThrow()
{
JObject o = new JObject();
((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(null, 0);
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"arrayIndex is less than 0.
Parameter name: arrayIndex")]
public void GenericCollectionCopyToNegativeArrayIndexShouldThrow()
{
JObject o = new JObject();
((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(new KeyValuePair<string, JToken>[1], -1);
}
[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"arrayIndex is equal to or greater than the length of array.")]
public void GenericCollectionCopyToArrayIndexEqualGreaterToArrayLengthShouldThrow()
{
JObject o = new JObject();
((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(new KeyValuePair<string, JToken>[1], 1);
}
[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.")]
public void GenericCollectionCopyToInsufficientArrayCapacity()
{
JObject o = new JObject();
o.Add("PropertyNameValue", new JValue(1));
o.Add("PropertyNameValue2", new JValue(2));
o.Add("PropertyNameValue3", new JValue(3));
((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(new KeyValuePair<string, JToken>[3], 1);
}
}
}
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Linq
{
public class JTokenEqualityComparerTests : TestFixtureBase
{
[Test]
public void JValueDictionary()
{
Dictionary<JToken, int> dic = new Dictionary<JToken, int>(JToken.EqualityComparer);
JValue v11 = new JValue(1);
JValue v12 = new JValue(1);
dic[v11] = 1;
dic[v12] += 1;
Assert.AreEqual(2, dic[v11]);
}
[Test]
public void JArrayDictionary()
{
Dictionary<JToken, int> dic = new Dictionary<JToken, int>(JToken.EqualityComparer);
JArray v11 = new JArray();
JArray v12 = new JArray();
dic[v11] = 1;
dic[v12] += 1;
Assert.AreEqual(2, dic[v11]);
}
[Test]
public void JObjectDictionary()
{
Dictionary<JToken, int> dic = new Dictionary<JToken, int>(JToken.EqualityComparer);
JObject v11 = new JObject() { { "Test", new JValue(1) }, { "Test1", new JValue(1) } };
JObject v12 = new JObject() { { "Test", new JValue(1) }, { "Test1", new JValue(1) } };
dic[v11] = 1;
dic[v12] += 1;
Assert.AreEqual(2, dic[v11]);
}
[Test]
public void JConstructorDictionary()
{
Dictionary<JToken, int> dic = new Dictionary<JToken, int>(JToken.EqualityComparer);
JConstructor v11 = new JConstructor("ConstructorValue");
JConstructor v12 = new JConstructor("ConstructorValue");
dic[v11] = 1;
dic[v12] += 1;
Assert.AreEqual(2, dic[v11]);
}
}
}
@@ -419,7 +419,7 @@ namespace Newtonsoft.Json.Tests.Linq
}
[Test]
[ExpectedException(typeof(Exception), ExpectedMessage = "Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArray")]
[ExpectedException(typeof(Exception), ExpectedMessage = "Can not add Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JArray.")]
public void AddPropertyToArray()
{
JArray a = new JArray();
@@ -427,7 +427,7 @@ namespace Newtonsoft.Json.Tests.Linq
}
[Test]
[ExpectedException(typeof(Exception), ExpectedMessage = "Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject")]
[ExpectedException(typeof(Exception), ExpectedMessage = "Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.")]
public void AddValueToObject()
{
JObject o = new JObject();
@@ -536,7 +536,7 @@ keyword such as type of business.""
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"Accessed JConstructor values with invalid key value: ""purple"". Argument position index expected.")]
public void JConstructorStringIndex()
{
JConstructor c = new JConstructor();
JConstructor c = new JConstructor("ConstructorValue");
Assert.AreEqual(null, c["purple"]);
}
@@ -78,6 +78,9 @@
<Compile Include="JsonTextWriterTest.cs" />
<Compile Include="JsonTokenReaderTest.cs" />
<Compile Include="JsonTokenWriterTest.cs" />
<Compile Include="Linq\JArrayTests.cs" />
<Compile Include="Linq\JObjectTests.cs" />
<Compile Include="Linq\JTokenEqualityComparerTests.cs" />
<Compile Include="Linq\JTokenTests.cs" />
<Compile Include="Linq\JValueTests.cs" />
<Compile Include="Linq\LinqToJsonTest.cs" />
+58 -19
View File
@@ -341,49 +341,88 @@ namespace Newtonsoft.Json
switch (convertible.GetTypeCode())
{
case TypeCode.String:
return ToString((string)convertible);
return ToString(convertible.ToString(CultureInfo.InvariantCulture));
case TypeCode.Char:
return ToString((char)convertible);
return ToString(convertible.ToChar(CultureInfo.InvariantCulture));
case TypeCode.Boolean:
return ToString((bool)convertible);
return ToString(convertible.ToBoolean(CultureInfo.InvariantCulture));
case TypeCode.SByte:
return ToString((sbyte)convertible);
return ToString(convertible.ToSByte(CultureInfo.InvariantCulture));
case TypeCode.Int16:
return ToString((short)convertible);
return ToString(convertible.ToInt16(CultureInfo.InvariantCulture));
case TypeCode.UInt16:
return ToString((ushort)convertible);
return ToString(convertible.ToUInt16(CultureInfo.InvariantCulture));
case TypeCode.Int32:
return ToString((int)convertible);
return ToString(convertible.ToInt32(CultureInfo.InvariantCulture));
case TypeCode.Byte:
return ToString((byte)convertible);
return ToString(convertible.ToByte(CultureInfo.InvariantCulture));
case TypeCode.UInt32:
return ToString((uint)convertible);
return ToString(convertible.ToUInt32(CultureInfo.InvariantCulture));
case TypeCode.Int64:
return ToString((long)convertible);
return ToString(convertible.ToInt64(CultureInfo.InvariantCulture));
case TypeCode.UInt64:
return ToString((ulong)convertible);
return ToString(convertible.ToUInt64(CultureInfo.InvariantCulture));
case TypeCode.Single:
return ToString((float)convertible);
return ToString(convertible.ToSingle(CultureInfo.InvariantCulture));
case TypeCode.Double:
return ToString((double)convertible);
return ToString(convertible.ToDouble(CultureInfo.InvariantCulture));
case TypeCode.DateTime:
return ToString((DateTime)convertible);
return ToString(convertible.ToDateTime(CultureInfo.InvariantCulture));
case TypeCode.Decimal:
return ToString((decimal)convertible);
return ToString(convertible.ToDecimal(CultureInfo.InvariantCulture));
case TypeCode.DBNull:
return Null;
}
}
else if (value is DateTimeOffset)
{
return ToString((DateTimeOffset)value);
}
else if (value is Guid)
{
return ToString((Guid)value);
}
throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
}
internal static bool IsJsonPrimitive(object value)
{
if (value == null)
{
return true;
}
else if (value is IConvertible)
{
IConvertible convertible = value as IConvertible;
switch (convertible.GetTypeCode())
{
case TypeCode.String:
case TypeCode.Char:
case TypeCode.Boolean:
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.Byte:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.DateTime:
case TypeCode.Decimal:
case TypeCode.DBNull:
return true;
default:
return false;
}
}
else if (value is DateTimeOffset)
{
return true;
}
return false;
}
/// <summary>
/// Serializes the specified object to a JSON string.
/// </summary>
+2 -61
View File
@@ -645,68 +645,9 @@ namespace Newtonsoft.Json
{
converter.WriteJson(writer, value);
}
else if (value is IConvertible)
else if (JavaScriptConvert.IsJsonPrimitive(value))
{
IConvertible convertible = value as IConvertible;
switch (convertible.GetTypeCode())
{
case TypeCode.String:
writer.WriteValue(convertible.ToString(CultureInfo.InvariantCulture));
break;
case TypeCode.Char:
writer.WriteValue(convertible.ToChar(CultureInfo.InvariantCulture));
break;
case TypeCode.Boolean:
writer.WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture));
break;
case TypeCode.SByte:
writer.WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture));
break;
case TypeCode.Int16:
writer.WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture));
break;
case TypeCode.UInt16:
writer.WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture));
break;
case TypeCode.Int32:
writer.WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture));
break;
case TypeCode.Byte:
writer.WriteValue(convertible.ToByte(CultureInfo.InvariantCulture));
break;
case TypeCode.UInt32:
writer.WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture));
break;
case TypeCode.Int64:
writer.WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture));
break;
case TypeCode.UInt64:
writer.WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture));
break;
case TypeCode.Single:
writer.WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture));
break;
case TypeCode.Double:
writer.WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture));
break;
case TypeCode.DateTime:
writer.WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture));
break;
case TypeCode.Decimal:
writer.WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture));
break;
case TypeCode.DBNull:
writer.WriteNull();
break;
default:
SerializeObject(writer, value);
break;
}
}
else if (value is DateTimeOffset)
{
writer.WriteValue((DateTimeOffset)value);
writer.WriteValue(value);
}
else if (value is IList)
{
+76
View File
@@ -736,6 +736,82 @@ namespace Newtonsoft.Json
{
AutoComplete(JsonToken.Date);
}
/// <summary>
/// Writes a <see cref="Object"/> value.
/// An error will raised if the value cannot be written as a single JSON token.
/// </summary>
/// <param name="value">The <see cref="Object"/> value to write.</param>
public virtual void WriteValue(object value)
{
if (value == null)
{
WriteNull();
}
else if (value is IConvertible)
{
IConvertible convertible = value as IConvertible;
switch (convertible.GetTypeCode())
{
case TypeCode.String:
WriteValue(convertible.ToString(CultureInfo.InvariantCulture));
return;
case TypeCode.Char:
WriteValue(convertible.ToChar(CultureInfo.InvariantCulture));
return;
case TypeCode.Boolean:
WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture));
return;
case TypeCode.SByte:
WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture));
return;
case TypeCode.Int16:
WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture));
return;
case TypeCode.UInt16:
WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture));
return;
case TypeCode.Int32:
WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture));
return;
case TypeCode.Byte:
WriteValue(convertible.ToByte(CultureInfo.InvariantCulture));
return;
case TypeCode.UInt32:
WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture));
return;
case TypeCode.Int64:
WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture));
return;
case TypeCode.UInt64:
WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture));
return;
case TypeCode.Single:
WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture));
return;
case TypeCode.Double:
WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture));
return;
case TypeCode.DateTime:
WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture));
return;
case TypeCode.Decimal:
WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture));
return;
case TypeCode.DBNull:
WriteNull();
return;
}
}
else if (value is DateTimeOffset)
{
WriteValue((DateTimeOffset)value);
return;
}
throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
}
#endregion
/// <summary>
+31 -5
View File
@@ -220,12 +220,22 @@ namespace Newtonsoft.Json.Linq
public void Insert(int index, JToken item)
{
JToken token = GetIndex(this, index);
AddInternal(false, token.Previous, item);
if (index == 0)
{
AddFirst(item);
}
else
{
JToken token = GetIndex(this, index);
AddInternal(false, token.Previous, item);
}
}
public void RemoveAt(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("index", "index is less than 0.");
int currentIndex = 0;
foreach (JToken token in Children())
{
@@ -237,18 +247,20 @@ namespace Newtonsoft.Json.Linq
currentIndex++;
}
throw new ArgumentOutOfRangeException("index", "index is equal to or greater than Count.");
}
#endregion
#region ICollection<JToken> Members
void ICollection<JToken>.Add(JToken item)
public void Add(JToken item)
{
Add((object)item);
}
void ICollection<JToken>.Clear()
public void Clear()
{
RemoveAll();
}
@@ -260,6 +272,15 @@ namespace Newtonsoft.Json.Linq
void ICollection<JToken>.CopyTo(JToken[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("array");
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
if (arrayIndex >= array.Length)
throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
if (Count > array.Length - arrayIndex)
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 (JToken token in Children())
{
@@ -278,7 +299,7 @@ namespace Newtonsoft.Json.Linq
get { return false; }
}
bool ICollection<JToken>.Remove(JToken item)
public bool Remove(JToken item)
{
if (!((ICollection<JToken>)this).Contains(item))
return false;
@@ -288,5 +309,10 @@ namespace Newtonsoft.Json.Linq
}
#endregion
internal override int GetDeepHashCode()
{
return ContentsHashCode();
}
}
}
+7 -7
View File
@@ -58,13 +58,6 @@ namespace Newtonsoft.Json.Linq
get { return JsonTokenType.Constructor; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class.
/// </summary>
public JConstructor()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class from another <see cref="JConstructor"/> object.
/// </summary>
@@ -102,6 +95,8 @@ namespace Newtonsoft.Json.Linq
/// <param name="name">The constructor name.</param>
public JConstructor(string name)
{
ValidationUtils.ArgumentNotNullOrEmpty(name, "name");
_name = name;
}
@@ -160,5 +155,10 @@ namespace Newtonsoft.Json.Linq
return GetIndex(this, (int)key);
}
}
internal override int GetDeepHashCode()
{
return _name.GetHashCode() ^ ContentsHashCode();
}
}
}
+13 -4
View File
@@ -261,7 +261,7 @@ namespace Newtonsoft.Json.Linq
if (previous != null)
previous.Next = o;
if (isLast)
if (isLast || previous == null)
_content = o;
}
}
@@ -271,7 +271,7 @@ namespace Newtonsoft.Json.Linq
ValidationUtils.ArgumentNotNull(o, "o");
if (o.Type == JsonTokenType.Property)
throw new Exception("Can not add {0} to {1}".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
throw new Exception("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
}
/// <summary>
@@ -422,8 +422,7 @@ namespace Newtonsoft.Json.Linq
parent = parent.Parent;
break;
case JsonToken.StartConstructor:
JConstructor constructor = new JConstructor();
constructor.Name = r.Value.ToString();
JConstructor constructor = new JConstructor(r.Value.ToString());
parent.AddObjectSkipNotify(constructor);
parent = constructor;
break;
@@ -460,5 +459,15 @@ namespace Newtonsoft.Json.Linq
}
while (r.Read());
}
internal int ContentsHashCode()
{
int hashCode = 0;
foreach (JToken item in Children())
{
hashCode ^= item.GetDeepHashCode();
}
return hashCode;
}
}
}
+21 -1
View File
@@ -83,7 +83,12 @@ namespace Newtonsoft.Json.Linq
ValidationUtils.ArgumentNotNull(o, "o");
if (o.Type != JsonTokenType.Property)
throw new Exception("Can not add {0} to {1}".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
throw new Exception("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
JProperty property = (JProperty)o;
bool matchingProperty = (Properties().Where(p => string.Compare(p.Name, property.Name, StringComparison.Ordinal) == 0).Count() > 0);
if (matchingProperty)
throw new Exception("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, property.Name, GetType()));
}
internal override JToken CloneNode()
@@ -319,10 +324,20 @@ namespace Newtonsoft.Json.Linq
void ICollection<KeyValuePair<string,JToken>>.CopyTo(KeyValuePair<string, JToken>[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("array");
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
if (arrayIndex >= array.Length)
throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
if (Count > array.Length - arrayIndex)
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 Properties())
{
array[arrayIndex + index] = new KeyValuePair<string, JToken>(property.Name, property.Value);
index++;
}
}
@@ -358,5 +373,10 @@ namespace Newtonsoft.Json.Linq
}
#endregion
internal override int GetDeepHashCode()
{
return ContentsHashCode();
}
}
}
+6 -1
View File
@@ -110,7 +110,7 @@ namespace Newtonsoft.Json.Linq
/// <param name="value">The property value.</param>
public JProperty(string name, object value)
{
ValidationUtils.ArgumentNotNullOrEmpty(name, "name");
ValidationUtils.ArgumentNotNull(name, "name");
_name = name;
Value = CreateFromContent(value);
@@ -149,5 +149,10 @@ namespace Newtonsoft.Json.Linq
// return (JValue)value;
//}
internal override int GetDeepHashCode()
{
return _name.GetHashCode() ^ ((Value != null) ? Value.GetDeepHashCode() : 0);
}
}
}
+14
View File
@@ -42,6 +42,18 @@ namespace Newtonsoft.Json.Linq
{
private JContainer _parent;
internal JToken _next;
private static JTokenEqualityComparer _equalityComparer;
public static JTokenEqualityComparer EqualityComparer
{
get
{
if (_equalityComparer == null)
_equalityComparer = new JTokenEqualityComparer();
return _equalityComparer;
}
}
/// <summary>
/// Gets or sets the parent.
@@ -705,5 +717,7 @@ namespace Newtonsoft.Json.Linq
{
return Children().GetEnumerator();
}
internal abstract int GetDeepHashCode();
}
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Newtonsoft.Json.Linq
{
public class JTokenEqualityComparer : IEqualityComparer<JToken>
{
public bool Equals(JToken x, JToken y)
{
return JToken.DeepEquals(x, y);
}
public int GetHashCode(JToken obj)
{
if (obj == null)
return 0;
return obj.GetDeepHashCode();
}
}
}
+7
View File
@@ -289,5 +289,12 @@ namespace Newtonsoft.Json.Linq
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", _valueType, "Unexpected token type.");
}
}
internal override int GetDeepHashCode()
{
int valueHashCode = (_value != null) ? _value.GetHashCode() : 0;
return _valueType.GetHashCode() ^ valueHashCode;
}
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ namespace Newtonsoft.Json.Linq
{
base.WriteStartConstructor(name);
AddParent(new JConstructor());
AddParent(new JConstructor(name));
}
/// <summary>
@@ -76,6 +76,7 @@
<ItemGroup>
<Compile Include="JsonConverterAttribute.cs" />
<Compile Include="JsonObjectAttribute.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />
<Compile Include="MemberSerialization.cs" />
<Compile Include="ObjectCreationHandling.cs" />
<Compile Include="Converters\IsoDateTimeConverter.cs" />