-Added type descriptor objects to support JObject property databinding

-Added OnErrorAttribute and ErrorContext for handling serialization errors
This commit is contained in:
JamesNK
2009-08-22 12:01:24 +00:00
parent 5167415f47
commit 95caaf9dc1
37 changed files with 1707 additions and 82 deletions
@@ -512,6 +512,17 @@ namespace Newtonsoft.Json.Tests.Converters
Assert.AreEqual(@"<myRoot><available_sizes><available_sizes><available_sizes>113</available_sizes><available_sizes>150</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes></available_sizes><available_sizes><available_sizes><available_sizes>189</available_sizes><available_sizes>250</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes></available_sizes><available_sizes><available_sizes><available_sizes>341</available_sizes><available_sizes>450</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-450x450.jpg</available_sizes></available_sizes></myRoot>", newDoc.InnerXml);
}
[Test]
public void Encoding()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(@"<name>O""Connor</name>"); // i use "" so it will be easier to see the problem
string json = JsonConvert.SerializeXmlNode(doc);
Assert.AreEqual(@"{""name"":""O\""Connor""}", json);
}
}
}
#endif
@@ -0,0 +1,79 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !PocketPC && !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.Web.UI;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Linq.ComponentModel
{
public class BindingTests : TestFixtureBase
{
[Test]
public void DataBinderEval()
{
JObject o = new JObject(
new JProperty("First", "String!"),
new JProperty("Second", 12345.6789m),
new JProperty("Third", new JArray(
1,
2,
3,
4,
5,
new JObject(
new JProperty("Fourth", "String!"),
new JProperty("Fifth", new JObject(
new JProperty("Sixth", "String!")))))));
object value;
value = DataBinder.Eval(o, "First");
Assert.AreEqual(value, (string)o["First"]);
value = DataBinder.Eval(o, "Second");
Assert.AreEqual(value, (decimal)o["Second"]);
value = DataBinder.Eval(o, "Third");
Assert.AreEqual(value, o["Third"]);
value = DataBinder.Eval(o, "Third[0]");
// urg!
Assert.AreEqual((int)(JToken)value, (int)o["Third"][0]);
value = DataBinder.Eval(o, "Third[5].Fourth");
Assert.AreEqual(value, (string)o["Third"][5]["Fourth"]);
value = DataBinder.Eval(o, "Third[5].Fifth.Sixth");
Assert.AreEqual(value, (string)o["Third"][5]["Fifth"]["Sixth"]);
}
}
}
#endif
@@ -0,0 +1,91 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq.ComponentModel;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Linq.ComponentModel
{
public class JPropertyDescriptorTests : TestFixtureBase
{
[Test]
public void GetValue()
{
JObject o = JObject.Parse("{prop1:'12345!',prop2:[1,'two','III']}");
JPropertyDescriptor prop1 = new JPropertyDescriptor("prop1", typeof(string));
JPropertyDescriptor prop2 = new JPropertyDescriptor("prop2", typeof(JArray));
Assert.AreEqual("12345!", prop1.GetValue(o));
Assert.AreEqual(o["prop2"], prop2.GetValue(o));
}
[Test]
public void SetValue()
{
JObject o = JObject.Parse("{prop1:'12345!'}");
JPropertyDescriptor propertyDescriptor1 = new JPropertyDescriptor("prop1", typeof(string));
propertyDescriptor1.SetValue(o, "54321!");
Assert.AreEqual("54321!", (string)o["prop1"]);
}
[Test]
public void ResetValue()
{
JObject o = JObject.Parse("{prop1:'12345!'}");
JPropertyDescriptor propertyDescriptor1 = new JPropertyDescriptor("prop1", typeof(string));
propertyDescriptor1.ResetValue(o);
Assert.AreEqual("12345!", (string)o["prop1"]);
}
[Test]
public void IsReadOnly()
{
JPropertyDescriptor propertyDescriptor1 = new JPropertyDescriptor("prop1", typeof(string));
Assert.AreEqual(false, propertyDescriptor1.IsReadOnly);
}
[Test]
public void PropertyType()
{
JPropertyDescriptor propertyDescriptor1 = new JPropertyDescriptor("prop1", typeof(string));
Assert.AreEqual(typeof(string), propertyDescriptor1.PropertyType);
}
}
}
#endif
@@ -0,0 +1,49 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !PocketPC && !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
using System.ComponentModel;
using Newtonsoft.Json.Linq.ComponentModel;
namespace Newtonsoft.Json.Tests.Linq.ComponentModel
{
public class JTypeDescriptionProviderTests : TestFixtureBase
{
[Test]
public void GetTypeDescriptor()
{
JTypeDescriptionProvider provider = new JTypeDescriptionProvider();
JTypeDescriptor descriptor = (JTypeDescriptor)provider.GetTypeDescriptor(typeof (JObject), new JObject());
Assert.IsNotNull(descriptor);
}
}
}
#endif
@@ -0,0 +1,80 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq.ComponentModel;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
using System.ComponentModel;
namespace Newtonsoft.Json.Tests.Linq.ComponentModel
{
public class JTypeDescriptorTests : TestFixtureBase
{
[Test]
public void GetProperties()
{
JObject o = JObject.Parse("{'prop1':12,'prop2':'hi!','prop3':null,'prop4':[1,2,3]}");
JTypeDescriptor descriptor = new JTypeDescriptor(o);
PropertyDescriptorCollection properties = descriptor.GetProperties();
Assert.AreEqual(4, properties.Count);
PropertyDescriptor prop1 = properties[0];
Assert.AreEqual("prop1", prop1.Name);
Assert.AreEqual(typeof(long), prop1.PropertyType);
Assert.AreEqual(typeof(JObject), prop1.ComponentType);
Assert.AreEqual(false, prop1.CanResetValue(o));
Assert.AreEqual(false, prop1.ShouldSerializeValue(o));
PropertyDescriptor prop2 = properties[1];
Assert.AreEqual("prop2", prop2.Name);
Assert.AreEqual(typeof(string), prop2.PropertyType);
Assert.AreEqual(typeof(JObject), prop2.ComponentType);
Assert.AreEqual(false, prop2.CanResetValue(o));
Assert.AreEqual(false, prop2.ShouldSerializeValue(o));
PropertyDescriptor prop3 = properties[2];
Assert.AreEqual("prop3", prop3.Name);
Assert.AreEqual(typeof(object), prop3.PropertyType);
Assert.AreEqual(typeof(JObject), prop3.ComponentType);
Assert.AreEqual(false, prop3.CanResetValue(o));
Assert.AreEqual(false, prop3.ShouldSerializeValue(o));
PropertyDescriptor prop4 = properties[3];
Assert.AreEqual("prop4", prop4.Name);
Assert.AreEqual(typeof(JArray), prop4.PropertyType);
Assert.AreEqual(typeof(JObject), prop4.ComponentType);
Assert.AreEqual(false, prop4.CanResetValue(o));
Assert.AreEqual(false, prop4.ShouldSerializeValue(o));
}
}
}
#endif
@@ -7,6 +7,9 @@ using NUnit.Framework;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using System.IO;
#if !PocketPC && !SILVERLIGHT
using System.Web.UI;
#endif
namespace Newtonsoft.Json.Tests.Linq
{
@@ -556,5 +559,107 @@ Parameter name: arrayIndex")]
// "JobTitle": "Manager"
//}
}
#if !PocketPC && !SILVERLIGHT
[Test]
public void PropertyChanging()
{
object changing = null;
object changed = null;
int changingCount = 0;
int changedCount = 0;
JObject o = new JObject();
o.PropertyChanging += (sender, args) =>
{
JObject s = (JObject) sender;
changing = (s[args.PropertyName] != null) ? ((JValue)s[args.PropertyName]).Value : null;
changingCount++;
};
o.PropertyChanged += (sender, args) =>
{
JObject s = (JObject)sender;
changed = (s[args.PropertyName] != null) ? ((JValue)s[args.PropertyName]).Value : null;
changedCount++;
};
o["StringValue"] = "value1";
Assert.AreEqual(null, changing);
Assert.AreEqual("value1", changed);
Assert.AreEqual("value1", (string)o["StringValue"]);
Assert.AreEqual(1, changingCount);
Assert.AreEqual(1, changedCount);
o["StringValue"] = "value1";
Assert.AreEqual(1, changingCount);
Assert.AreEqual(1, changedCount);
o["StringValue"] = "value2";
Assert.AreEqual("value1", changing);
Assert.AreEqual("value2", changed);
Assert.AreEqual("value2", (string)o["StringValue"]);
Assert.AreEqual(2, changingCount);
Assert.AreEqual(2, changedCount);
o["StringValue"] = null;
Assert.AreEqual("value2", changing);
Assert.AreEqual(null, changed);
Assert.AreEqual(null, (string)o["StringValue"]);
Assert.AreEqual(3, changingCount);
Assert.AreEqual(3, changedCount);
o["NullValue"] = null;
Assert.AreEqual(null, changing);
Assert.AreEqual(null, changed);
Assert.AreEqual(new JValue((object)null), o["NullValue"]);
Assert.AreEqual(4, changingCount);
Assert.AreEqual(4, changedCount);
o["NullValue"] = null;
Assert.AreEqual(4, changingCount);
Assert.AreEqual(4, changedCount);
}
#endif
[Test]
public void PropertyChanged()
{
object changed = null;
int changedCount = 0;
JObject o = new JObject();
o.PropertyChanged += (sender, args) =>
{
JObject s = (JObject)sender;
changed = (s[args.PropertyName] != null) ? ((JValue)s[args.PropertyName]).Value : null;
changedCount++;
};
o["StringValue"] = "value1";
Assert.AreEqual("value1", changed);
Assert.AreEqual("value1", (string)o["StringValue"]);
Assert.AreEqual(1, changedCount);
o["StringValue"] = "value1";
Assert.AreEqual(1, changedCount);
o["StringValue"] = "value2";
Assert.AreEqual("value2", changed);
Assert.AreEqual("value2", (string)o["StringValue"]);
Assert.AreEqual(2, changedCount);
o["StringValue"] = null;
Assert.AreEqual(null, changed);
Assert.AreEqual(null, (string)o["StringValue"]);
Assert.AreEqual(3, changedCount);
o["NullValue"] = null;
Assert.AreEqual(null, changed);
Assert.AreEqual(new JValue((object)null), o["NullValue"]);
Assert.AreEqual(4, changedCount);
o["NullValue"] = null;
Assert.AreEqual(4, changedCount);
}
}
}
@@ -61,6 +61,10 @@
<ItemGroup>
<Compile Include="Converters\BinaryConverterTests.cs" />
<Compile Include="Converters\StringEnumConverterTests.cs" />
<Compile Include="Linq\ComponentModel\BindingTests.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptorTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProviderTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptorTests.cs" />
<Compile Include="Linq\JTokenReaderTest.cs" />
<Compile Include="Linq\JTokenWriterTest.cs" />
<Compile Include="JsonValidatingReaderTests.cs" />
@@ -69,6 +73,7 @@
<Compile Include="Schema\JsonSchemaNodeTests.cs" />
<Compile Include="Serialization\CamelCasePropertyNamesContractResolverTests.cs" />
<Compile Include="Serialization\EntitiesSerializationTests.cs" />
<Compile Include="Serialization\JsonSerializerTest.cs" />
<Compile Include="Serialization\PopulateTests.cs" />
<Compile Include="Serialization\PreserveReferencesHandlingTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
@@ -132,7 +137,6 @@
<Compile Include="Converters\IsoDateTimeConverterTests.cs" />
<Compile Include="JsonConvertTest.cs" />
<Compile Include="Converters\JavaScriptDateTimeConverterTests.cs" />
<Compile Include="JsonSerializerTest.cs" />
<Compile Include="JsonTextReaderTest.cs" />
<Compile Include="JsonTextWriterTest.cs" />
<Compile Include="Linq\JArrayTests.cs" />
@@ -68,7 +68,12 @@
<Compile Include="JsonArrayAttributeTests.cs" />
<Compile Include="ExceptionTests.cs" />
<Compile Include="JsonValidatingReaderTests.cs" />
<Compile Include="Linq\ComponentModel\BindingTests.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptorTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProviderTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptorTests.cs" />
<Compile Include="Serialization\EntitiesSerializationTests.cs" />
<Compile Include="Serialization\JsonSerializerTest.cs" />
<Compile Include="Serialization\PopulateTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
<Compile Include="Schema\ExtensionsTests.cs" />
@@ -136,7 +141,6 @@
<Compile Include="Converters\IsoDateTimeConverterTests.cs" />
<Compile Include="JsonConvertTest.cs" />
<Compile Include="Converters\JavaScriptDateTimeConverterTests.cs" />
<Compile Include="JsonSerializerTest.cs" />
<Compile Include="JsonTextReaderTest.cs" />
<Compile Include="JsonTextWriterTest.cs" />
<Compile Include="Linq\JTokenReaderTest.cs" />
@@ -67,6 +67,10 @@
<Compile Include="Converters\StringEnumConverterTests.cs" />
<Compile Include="ExceptionTests.cs" />
<Compile Include="JsonArrayAttributeTests.cs" />
<Compile Include="Linq\ComponentModel\BindingTests.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptorTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProviderTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptorTests.cs" />
<Compile Include="Linq\JTokenReaderTest.cs" />
<Compile Include="Linq\JTokenWriterTest.cs" />
<Compile Include="JsonValidatingReaderTests.cs" />
@@ -75,6 +79,7 @@
<Compile Include="Schema\JsonSchemaNodeTests.cs" />
<Compile Include="Serialization\CamelCasePropertyNamesContractResolverTests.cs" />
<Compile Include="Serialization\EntitiesSerializationTests.cs" />
<Compile Include="Serialization\JsonSerializerTest.cs" />
<Compile Include="Serialization\PopulateTests.cs" />
<Compile Include="Serialization\PreserveReferencesHandlingTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
@@ -138,7 +143,6 @@
<Compile Include="Converters\IsoDateTimeConverterTests.cs" />
<Compile Include="JsonConvertTest.cs" />
<Compile Include="Converters\JavaScriptDateTimeConverterTests.cs" />
<Compile Include="JsonSerializerTest.cs" />
<Compile Include="JsonTextReaderTest.cs" />
<Compile Include="JsonTextWriterTest.cs" />
<Compile Include="Linq\JArrayTests.cs" />
@@ -105,6 +105,10 @@
</Compile>
<Compile Include="LinqToSql\LinqToSqlClassesSerializationTests.cs" />
<Compile Include="LinqToSql\Person.cs" />
<Compile Include="Linq\ComponentModel\BindingTests.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptorTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProviderTests.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptorTests.cs" />
<Compile Include="Serialization\EntitiesSerializationTests.cs" />
<Compile Include="Serialization\PopulateTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
@@ -173,7 +177,7 @@
<Compile Include="Converters\IsoDateTimeConverterTests.cs" />
<Compile Include="JsonConvertTest.cs" />
<Compile Include="Converters\JavaScriptDateTimeConverterTests.cs" />
<Compile Include="JsonSerializerTest.cs" />
<Compile Include="Serialization\JsonSerializerTest.cs" />
<Compile Include="JsonTextReaderTest.cs" />
<Compile Include="JsonTextWriterTest.cs" />
<Compile Include="Linq\JTokenReaderTest.cs" />
@@ -46,7 +46,7 @@ using Newtonsoft.Json.Tests.TestObjects;
using System.Runtime.Serialization;
using System.Globalization;
namespace Newtonsoft.Json.Tests
namespace Newtonsoft.Json.Tests.Serialization
{
public class JsonSerializerTest : TestFixtureBase
{
@@ -1291,7 +1291,7 @@ keyword such as type of business.""
}
[Test]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Could not create an instance of type Newtonsoft.Json.Tests.JsonSerializerTest+ICo. Type is an interface or abstract class and cannot be instantated.")]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Could not create an instance of type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ICo. Type is an interface or abstract class and cannot be instantated.")]
public void DeserializeInterfaceProperty()
{
Test testClass = new Test();
@@ -2049,5 +2049,158 @@ keyword such as type of business.""
NullableDateTimeTestClass c = JsonConvert.DeserializeObject<NullableDateTimeTestClass>(json);
Assert.AreEqual(null, c.DateTimeField);
}
/// <summary>
/// What types of events are there? Just sticking to a basic set of four for now.
/// </summary>
/// <remarks></remarks>
public enum EventType
{
Debug = 0,
Info = 1,
Warning = 2,
Error = 3
}
public sealed class Event
{
/// <summary>
/// If no current user is specified, returns Nothing (0 from VB)
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
private static int GetCurrentUserId()
{
return 0;
}
/// <summary>
/// Gets either the application path or the current stack trace.
/// NOTE: You MUST call this from the top level entry point. Otherwise,
/// the stack trace will be buried in Logger itself.
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
private static string GetCurrentSubLocation()
{
return "";
}
private string _sublocation;
private int _userId;
private EventType _type;
private string _summary;
private string _details;
private string _stackTrace;
private string _tag;
private DateTime _time;
public Event(string summary)
{
_summary = summary;
_time = DateTime.Now;
if (_userId == 0) _userId = GetCurrentUserId();
//This call only works at top level for now.
//If _stackTrace = Nothing Then _stackTrace = Environment.StackTrace
if (_sublocation == null) _sublocation = GetCurrentSubLocation();
}
public Event(string sublocation, int userId, EventType type, string summary, string details, string stackTrace, string tag)
{
_sublocation = sublocation;
_userId = userId;
_type = type;
_summary = summary;
_details = details;
_stackTrace = stackTrace;
_tag = tag;
_time = DateTime.Now;
if (_userId == 0) _userId = GetCurrentUserId();
//If _stackTrace = Nothing Then _stackTrace = Environment.StackTrace
if (_sublocation == null) _sublocation = GetCurrentSubLocation();
}
public override string ToString()
{
return string.Format("{{ sublocation = {0}, userId = {1}, type = {2}, summary = {3}, details = {4}, stackTrace = {5}, tag = {6} }}", _sublocation, _userId, _type, _summary, _details, _stackTrace, _tag);
}
public string sublocation
{
get { return _sublocation; }
set { _sublocation = value; }
}
public int userId
{
get { return _userId; }
set { _userId = value; }
}
public EventType type
{
get { return _type; }
set { _type = value; }
}
public string summary
{
get { return _summary; }
set { _summary = value; }
}
public string details
{
get { return _details; }
set { _details = value; }
}
public string stackTrace
{
get { return _stackTrace; }
set { _stackTrace = value; }
}
public string tag
{
get { return _tag; }
set { _tag = value; }
}
public DateTime time
{
get { return _time; }
}
}
[Test]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Unable to determine which constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+Event. A class with no default constructor should have only one constructor with arguments.")]
public void FailWhenClassWithNoDefaultConstructorHasMultipleConstructorsWithArguments()
{
string json = @"{""sublocation"":""AlertEmailSender.Program.Main"",""userId"":0,""type"":0,""summary"":""Loading settings variables"",""details"":null,""stackTrace"":"" at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)\r\n at System.Environment.get_StackTrace()\r\n at mr.Logging.Event..ctor(String summary) in C:\\Projects\\MRUtils\\Logging\\Event.vb:line 71\r\n at AlertEmailSender.Program.Main(String[] args) in C:\\Projects\\AlertEmailSender\\AlertEmailSender\\Program.cs:line 25"",""tag"":null,""time"":""\/Date(1249591032026-0400)\/""}";
Event e = JsonConvert.DeserializeObject<Event>(json);
}
public class SetOnlyPropertyClass2
{
private object _value;
public object SetOnlyProperty
{
set { _value = value; }
}
public object GetValue()
{
return _value;
}
}
[Test]
public void DeserializeObjectSetOnlyProperty()
{
string json = @"{'SetOnlyProperty':[1,2,3,4,5]}";
SetOnlyPropertyClass2 setOnly = JsonConvert.DeserializeObject<SetOnlyPropertyClass2>(json);
JArray a = (JArray)setOnly.GetValue();
Assert.AreEqual(5, a.Count);
Assert.AreEqual(1, (int)a[0]);
Assert.AreEqual(5, (int)a[a.Count - 1]);
}
}
}
@@ -1,4 +1,29 @@
using System;
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -15,8 +40,7 @@ namespace Newtonsoft.Json.Tests.Serialization
{
Person p = new Person();
JsonSerializer serializer = new JsonSerializer();
serializer.Populate(new StringReader(@"{""Name"":""James""}"), p);
JsonConvert.PopulateObject(@"{""Name"":""James""}", p);
Assert.AreEqual("James", p.Name);
}
@@ -71,9 +95,10 @@ namespace Newtonsoft.Json.Tests.Serialization
]
}";
JsonSerializer serializer = new JsonSerializer();
serializer.ObjectCreationHandling = ObjectCreationHandling.Replace;
serializer.Populate(new StringReader(json), s);
JsonConvert.PopulateObject(json, s, new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace
});
Assert.AreEqual(1, s.Mottos.Count);
Assert.AreEqual("Fail whale", s.Mottos[0]);
@@ -26,13 +26,18 @@
#if !PocketPC && !SILVERLIGHT && !NET20
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Tests;
using Newtonsoft.Json.Tests.TestObjects;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
using System.Collections;
namespace Newtonsoft.Json.Tests.Serialization
{
@@ -47,6 +52,7 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual("Hello World!", obj.Member2);
Assert.AreEqual("This is a nonserialized value", obj.Member3);
Assert.AreEqual(null, obj.Member4);
Assert.AreEqual(null, obj.Member5);
string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Assert.AreEqual(@"{
@@ -59,13 +65,22 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual("This value was reset after serialization.", obj.Member2);
Assert.AreEqual("This is a nonserialized value", obj.Member3);
Assert.AreEqual(null, obj.Member4);
Assert.AreEqual("Error message for member Member6 = Exception has been thrown by the target of an invocation.", obj.Member5);
obj = JsonConvert.DeserializeObject<SerializationEventTestObject>(json);
JObject o = JObject.Parse(@"{
""Member1"": 11,
""Member2"": ""This value went into the data file during serialization."",
""Member4"": null
}");
o["Member6"] = "Dummy text for error";
obj = JsonConvert.DeserializeObject<SerializationEventTestObject>(o.ToString());
Assert.AreEqual(11, obj.Member1);
Assert.AreEqual("This value went into the data file during serialization.", obj.Member2);
Assert.AreEqual("This value was set during deserialization", obj.Member3);
Assert.AreEqual("This value was set after deserialization.", obj.Member4);
Assert.AreEqual("Error message for member Member6 = Exception has been thrown by the target of an invocation.", obj.Member5);
}
[Test]
@@ -98,6 +113,136 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual("This value was set after deserialization.", obj.Member4);
}
public class ListErrorObject
{
public string Member
{
get { throw new Exception("ListErrorObject.Member get error!"); }
set { throw new Exception("ListErrorObject.Member set error!"); }
}
}
public class ListErrorObjectCollection : Collection<ListErrorObject>
{
[OnError]
internal void OnErrorMethod(StreamingContext context, ErrorContext errorContext)
{
errorContext.Handled = true;
}
}
public class VersionKeyedCollection : KeyedCollection<string, Person>, IList
{
public List<string> Messages { get; set; }
public VersionKeyedCollection()
{
Messages = new List<string>();
}
protected override string GetKeyForItem(Person item)
{
return item.Name;
}
[OnError]
internal void OnErrorMethod(StreamingContext context, ErrorContext errorContext)
{
Messages.Add("Error message for member " + errorContext.Member + " = " + errorContext.Error.Message);
errorContext.Handled = true;
}
object IList.this[int index]
{
get
{
if (index % 2 == 0)
throw new Exception("Index even: " + index);
return this[index];
}
set { this[index] = (Person)value; }
}
}
[Test]
public void ErrorDeserializingListHandled()
{
string json = @"[
{
""Name"": ""Jim"",
""BirthDate"": ""\/Date(978048000000)\/"",
""LastModified"": ""\/Date(978048000000)\/""
},
{
""Name"": ""Jim"",
""BirthDate"": ""\/Date(978048000000)\/"",
""LastModified"": ""\/Date(978048000000)\/""
}
]";
VersionKeyedCollection c = JsonConvert.DeserializeObject<VersionKeyedCollection>(json);
Assert.AreEqual(1, c.Count);
Assert.AreEqual(1, c.Messages.Count);
Assert.AreEqual("Error message for member 1 = An item with the same key has already been added.", c.Messages[0]);
}
[Test]
public void ErrorSerializingListHandled()
{
VersionKeyedCollection c = new VersionKeyedCollection();
c.Add(new Person
{
Name = "Jim",
BirthDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
LastModified = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc)
});
c.Add(new Person
{
Name = "Jimbo",
BirthDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
LastModified = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc)
});
c.Add(new Person
{
Name = "Jimmy",
BirthDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
LastModified = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc)
});
c.Add(new Person
{
Name = "Jim Bean",
BirthDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
LastModified = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc)
});
string json = JsonConvert.SerializeObject(c, Formatting.Indented);
Assert.AreEqual(@"[
{
""Name"": ""Jimbo"",
""BirthDate"": ""\/Date(978048000000)\/"",
""LastModified"": ""\/Date(978048000000)\/""
},
{
""Name"": ""Jim Bean"",
""BirthDate"": ""\/Date(978048000000)\/"",
""LastModified"": ""\/Date(978048000000)\/""
}
]", json);
Assert.AreEqual(2, c.Messages.Count);
Assert.AreEqual("Error message for member 0 = Index even: 0", c.Messages[0]);
Assert.AreEqual("Error message for member 2 = Index even: 2", c.Messages[1]);
}
[Test]
[ExpectedException(typeof(TargetInvocationException))]
public void ErrorInChild()
{
JsonConvert.DeserializeObject<ListErrorObjectCollection>(@"[{""Member"":""Value""}]");
}
[Test]
public void ListEvents()
{
@@ -187,6 +332,8 @@ namespace Newtonsoft.Json.Tests.Serialization
// This is a nonserialized value
Console.WriteLine(obj.Member4);
// null
Console.WriteLine(obj.Member5);
// null
string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
// {
@@ -203,6 +350,8 @@ namespace Newtonsoft.Json.Tests.Serialization
// This is a nonserialized value
Console.WriteLine(obj.Member4);
// null
Console.WriteLine(obj.Member5);
// Error message for member Member6 = Exception has been thrown by the target of an invocation.
obj = JsonConvert.DeserializeObject<SerializationEventTestObject>(json);
@@ -26,6 +26,7 @@
#if !PocketPC && !SILVERLIGHT
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using Newtonsoft.Json.Tests.Serialization;
namespace Newtonsoft.Json.Tests.TestObjects
{
@@ -23,11 +23,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !PocketPC && !SILVERLIGHT
#if !PocketPC && !SILVERLIGHT && !NET20
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Tests.TestObjects
{
@@ -48,6 +49,17 @@ namespace Newtonsoft.Json.Tests.TestObjects
// This field is set to null, but populated after deserialization.
public string Member4 { get; set; }
// This field is set to null, but populated after error.
[JsonIgnore]
public string Member5 { get; set; }
// Getting or setting this field will throw an error.
public string Member6
{
get { throw new Exception("Member5 get error!"); }
set { throw new Exception("Member5 set error!"); }
}
public SerializationEventTestObject()
{
Member1 = 11;
@@ -79,6 +91,13 @@ namespace Newtonsoft.Json.Tests.TestObjects
{
Member4 = "This value was set after deserialization.";
}
[OnError]
internal void OnErrorMethod(StreamingContext context, ErrorContext errorContext)
{
Member5 = "Error message for member " + errorContext.Member + " = " + errorContext.Error.Message;
errorContext.Handled = true;
}
}
}
#endif
@@ -24,7 +24,9 @@
#endregion
#if !PocketPC && !SILVERLIGHT
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Tests.TestObjects
{
@@ -25,9 +25,6 @@
#if !PocketPC && !SILVERLIGHT && !NET20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Newtonsoft.Json.Serialization;
using System.Globalization;
@@ -53,7 +50,7 @@ namespace Newtonsoft.Json.Converters
if (keyType != null)
{
string valueJson;
if (JsonSerializerWriter.TryConvertToString(entityKeyMember.Value, keyType, out valueJson))
if (JsonSerializerInternalWriter.TryConvertToString(entityKeyMember.Value, keyType, out valueJson))
writer.WriteValue(valueJson);
else
writer.WriteValue(entityKeyMember.Value);
+20
View File
@@ -628,6 +628,26 @@ namespace Newtonsoft.Json
return deserializedValue;
}
public static void PopulateObject(string value, object target)
{
PopulateObject(value, target, null);
}
public static void PopulateObject(string value, object target, JsonSerializerSettings settings)
{
StringReader sr = new StringReader(value);
JsonSerializer jsonSerializer = JsonSerializer.Create(settings);
using (JsonReader jsonReader = new JsonTextReader(sr))
{
jsonSerializer.Populate(jsonReader, target);
if (jsonReader.Read() && jsonReader.TokenType != JsonToken.Comment)
throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object.");
}
}
#if !SILVERLIGHT
/// <summary>
/// Serializes the XML node to a JSON string.
+3 -3
View File
@@ -309,7 +309,7 @@ namespace Newtonsoft.Json
ValidationUtils.ArgumentNotNull(reader, "reader");
ValidationUtils.ArgumentNotNull(target, "target");
JsonSerializerReader serializerReader = new JsonSerializerReader(this);
JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
serializerReader.Populate(reader, target);
}
@@ -351,7 +351,7 @@ namespace Newtonsoft.Json
{
ValidationUtils.ArgumentNotNull(reader, "reader");
JsonSerializerReader serializerReader = new JsonSerializerReader(this);
JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
return serializerReader.Deserialize(reader, objectType);
}
@@ -381,7 +381,7 @@ namespace Newtonsoft.Json
{
ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
JsonSerializerWriter serializerWriter = new JsonSerializerWriter(this);
JsonSerializerInternalWriter serializerWriter = new JsonSerializerInternalWriter(this);
serializerWriter.Serialize(jsonWriter, value);
}
@@ -0,0 +1,158 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !SILVERLIGHT
using System;
using System.ComponentModel;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.ComponentModel
{
/// <summary>
/// Represents a view of a <see cref="JProperty"/>.
/// </summary>
public class JPropertyDescriptor : PropertyDescriptor
{
private readonly Type _propertyType;
/// <summary>
/// Initializes a new instance of the <see cref="JPropertyDescriptor"/> class.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="propertyType">Type of the property.</param>
public JPropertyDescriptor(string name, Type propertyType)
: base(name, null)
{
ValidationUtils.ArgumentNotNull(name, "name");
ValidationUtils.ArgumentNotNull(propertyType, "propertyType");
_propertyType = propertyType;
}
private static JObject CastInstance(object instance)
{
return (JObject)instance;
}
/// <summary>
/// When overridden in a derived class, returns whether resetting an object changes its value.
/// </summary>
/// <returns>
/// true if resetting the component changes its value; otherwise, false.
/// </returns>
/// <param name="component">The component to test for reset capability.
/// </param>
public override bool CanResetValue(object component)
{
return false;
}
/// <summary>
/// When overridden in a derived class, gets the current value of the property on a component.
/// </summary>
/// <returns>
/// The value of a property for a given component.
/// </returns>
/// <param name="component">The component with the property for which to retrieve the value.
/// </param>
public override object GetValue(object component)
{
JToken token = CastInstance(component)[Name];
if (token is JValue)
return ((JValue) token).Value;
return token;
}
/// <summary>
/// When overridden in a derived class, resets the value for this property of the component to the default value.
/// </summary>
/// <param name="component">The component with the property value that is to be reset to the default value.
/// </param>
public override void ResetValue(object component)
{
}
/// <summary>
/// When overridden in a derived class, sets the value of the component to a different value.
/// </summary>
/// <param name="component">The component with the property value that is to be set.
/// </param><param name="value">The new value.
/// </param>
public override void SetValue(object component, object value)
{
JToken token = (value is JToken) ? (JToken) value : new JValue(value);
CastInstance(component)[Name] = token;
}
/// <summary>
/// When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
/// </summary>
/// <returns>
/// true if the property should be persisted; otherwise, false.
/// </returns>
/// <param name="component">The component with the property to be examined for persistence.
/// </param>
public override bool ShouldSerializeValue(object component)
{
return false;
}
/// <summary>
/// When overridden in a derived class, gets the type of the component this property is bound to.
/// </summary>
/// <returns>
/// A <see cref="T:System.Type"/> that represents the type of component this property is bound to. When the <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"/> or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"/> methods are invoked, the object specified might be an instance of this type.
/// </returns>
public override Type ComponentType
{
get { return typeof(JObject); }
}
/// <summary>
/// When overridden in a derived class, gets a value indicating whether this property is read-only.
/// </summary>
/// <returns>
/// true if the property is read-only; otherwise, false.
/// </returns>
public override bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// When overridden in a derived class, gets the type of the property.
/// </summary>
/// <returns>
/// A <see cref="T:System.Type"/> that represents the type of the property.
/// </returns>
public override Type PropertyType
{
get { return _propertyType; }
}
}
}
#endif
@@ -0,0 +1,47 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !PocketPC && !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace Newtonsoft.Json.Linq.ComponentModel
{
internal class JTypeDescriptionProvider : TypeDescriptionProvider
{
public override ICustomTypeDescriptor GetTypeDescriptor(Type type, object instance)
{
JObject o = instance as JObject;
if (o != null)
return new JTypeDescriptor(o);
return base.GetTypeDescriptor(type, instance);
}
}
}
#endif
@@ -0,0 +1,209 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.ComponentModel
{
/// <summary>
/// Represents a view of a <see cref="JObject"/>.
/// </summary>
public class JTypeDescriptor : ICustomTypeDescriptor
{
private readonly JObject _value;
/// <summary>
/// Initializes a new instance of the <see cref="JTypeDescriptor"/> class.
/// </summary>
/// <param name="value">The value.</param>
public JTypeDescriptor(JObject value)
{
ValidationUtils.ArgumentNotNull(value, "value");
_value = value;
}
/// <summary>
/// Returns the properties for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the properties for this component instance.
/// </returns>
public virtual PropertyDescriptorCollection GetProperties()
{
return GetProperties(null);
}
private static Type GetTokenPropertyType(JToken token)
{
if (token is JValue)
{
JValue v = (JValue) token;
return (v.Value != null) ? v.Value.GetType() : typeof (object);
}
return token.GetType();
}
/// <summary>
/// Returns the properties for this instance of a component using the attribute array as a filter.
/// </summary>
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the filtered properties for this component instance.
/// </returns>
public virtual PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null);
if (_value != null)
{
foreach (KeyValuePair<string, JToken> propertyValue in _value)
{
descriptors.Add(new JPropertyDescriptor(propertyValue.Key, GetTokenPropertyType(propertyValue.Value)));
}
}
return descriptors;
}
/// <summary>
/// Returns a collection of custom attributes for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.AttributeCollection"/> containing the attributes for this object.
/// </returns>
public AttributeCollection GetAttributes()
{
return AttributeCollection.Empty;
}
/// <summary>
/// Returns the class name of this instance of a component.
/// </summary>
/// <returns>
/// The class name of the object, or null if the class does not have a name.
/// </returns>
public string GetClassName()
{
return null;
}
/// <summary>
/// Returns the name of this instance of a component.
/// </summary>
/// <returns>
/// The name of the object, or null if the object does not have a name.
/// </returns>
public string GetComponentName()
{
return null;
}
/// <summary>
/// Returns a type converter for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.TypeConverter"/> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter"/> for this object.
/// </returns>
public TypeConverter GetConverter()
{
return new TypeConverter();
}
/// <summary>
/// Returns the default event for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptor"/> that represents the default event for this object, or null if this object does not have events.
/// </returns>
public EventDescriptor GetDefaultEvent()
{
return null;
}
/// <summary>
/// Returns the default property for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the default property for this object, or null if this object does not have properties.
/// </returns>
public PropertyDescriptor GetDefaultProperty()
{
return null;
}
/// <summary>
/// Returns an editor of the specified type for this instance of a component.
/// </summary>
/// <param name="editorBaseType">A <see cref="T:System.Type"/> that represents the editor for this object.</param>
/// <returns>
/// An <see cref="T:System.Object"/> of the specified type that is the editor for this object, or null if the editor cannot be found.
/// </returns>
public object GetEditor(Type editorBaseType)
{
return null;
}
/// <summary>
/// Returns the events for this instance of a component using the specified attribute array as a filter.
/// </summary>
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the filtered events for this component instance.
/// </returns>
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return EventDescriptorCollection.Empty;
}
/// <summary>
/// Returns the events for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the events for this component instance.
/// </returns>
public EventDescriptorCollection GetEvents()
{
return EventDescriptorCollection.Empty;
}
/// <summary>
/// Returns an object that contains the property described by the specified property descriptor.
/// </summary>
/// <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the property whose owner is to be found.</param>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the owner of the specified property.
/// </returns>
public object GetPropertyOwner(PropertyDescriptor pd)
{
return null;
}
}
}
#endif
+1 -1
View File
@@ -204,7 +204,7 @@ namespace Newtonsoft.Json.Linq
{
if (IsMultiContent(content))
{
IEnumerable enumerable = content as IEnumerable;
IEnumerable enumerable = (IEnumerable)content;
JToken multiPrevious = previous;
foreach (object c in enumerable)
+67 -5
View File
@@ -25,19 +25,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.IO;
using Newtonsoft.Json.Utilities;
using System.Globalization;
#if !PocketPC && !SILVERLIGHT
using Newtonsoft.Json.Linq.ComponentModel;
#endif
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a JSON object.
/// </summary>
public class JObject : JContainer, IDictionary<string, JToken>
#if !PocketPC && !SILVERLIGHT
[TypeDescriptionProvider(typeof(JTypeDescriptionProvider))]
#endif
public class JObject : JContainer, IDictionary<string, JToken>, INotifyPropertyChanged
#if !PocketPC && !SILVERLIGHT
, INotifyPropertyChanging
#endif
{
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#if !PocketPC && !SILVERLIGHT
/// <summary>
/// Occurs when a property value is changing.
/// </summary>
public event PropertyChangingEventHandler PropertyChanging;
#endif
/// <summary>
/// Initializes a new instance of the <see cref="JObject"/> class.
/// </summary>
@@ -171,12 +191,42 @@ namespace Newtonsoft.Json.Linq
{
JProperty property = Property(propertyName);
if (property != null)
property.Value = value;
{
if (!IsTokenUnchanged(property.Value, value))
{
#if !PocketPC && !SILVERLIGHT
OnPropertyChanging(property.Name);
#endif
property.Value = value;
OnPropertyChanged(property.Name);
}
}
else
{
#if !PocketPC && !SILVERLIGHT
OnPropertyChanging(propertyName);
#endif
Add(new JProperty(propertyName, value));
OnPropertyChanged(propertyName);
}
}
}
private static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
{
JValue v1 = currentValue as JValue;
if (v1 != null)
{
// null will get turned into a JValue of type null
if (v1.Type == JTokenType.Null && newValue == null)
return true;
return v1.Equals(newValue);
}
return false;
}
/// <summary>
/// Loads an <see cref="JObject"/> from a <see cref="JsonReader"/>.
/// </summary>
@@ -219,7 +269,6 @@ namespace Newtonsoft.Json.Linq
return Load(jsonReader);
}
/// <summary>
/// Creates a <see cref="JObject"/> from an object.
/// </summary>
@@ -246,7 +295,6 @@ namespace Newtonsoft.Json.Linq
return (JObject)token;
}
internal override void ValidateObject(JToken o, JToken previous)
{
ValidationUtils.ArgumentNotNull(o, "o");
@@ -418,5 +466,19 @@ namespace Newtonsoft.Json.Linq
yield return new KeyValuePair<string, JToken>(property.Name, property.Value);
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#if !PocketPC && !SILVERLIGHT
protected virtual void OnPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
#endif
}
}
+46 -1
View File
@@ -35,7 +35,7 @@ namespace Newtonsoft.Json.Linq
/// <summary>
/// Represents a value in JSON (string, integer, date, etc).
/// </summary>
public class JValue : JToken
public class JValue : JToken, IEquatable<JValue>
{
private JTokenType _valueType;
private object _value;
@@ -327,5 +327,50 @@ namespace Newtonsoft.Json.Linq
return _valueType.GetHashCode() ^ valueHashCode;
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <returns>
/// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
/// </returns>
/// <param name="other">An object to compare with this object.</param>
public bool Equals(JValue other)
{
if (other == null)
return false;
return (_value == other._value);
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
/// <returns>
/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
/// </returns>
/// <exception cref="T:System.NullReferenceException">
/// The <paramref name="obj"/> parameter is null.
/// </exception>
public override bool Equals(object obj)
{
if (obj == null)
return false;
JValue otherValue = obj as JValue;
if (otherValue != null)
return Equals(otherValue);
return base.Equals(obj);
}
public override int GetHashCode()
{
if (_value == null)
return 0;
return _value.GetHashCode();
}
}
}
@@ -70,6 +70,9 @@
<Compile Include="JsonObjectAttribute.cs" />
<Compile Include="JsonSerializerSettings.cs" />
<Compile Include="JsonValidatingReader.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProvider.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptor.cs" />
<Compile Include="Linq\IJEnumerable.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />
<Compile Include="Linq\JTokenReader.cs" />
@@ -121,6 +124,7 @@
<Compile Include="Serialization\DefaultContractResolver.cs" />
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
<Compile Include="Serialization\ErrorContext.cs" />
<Compile Include="Serialization\IContractResolver.cs" />
<Compile Include="Serialization\IReferenceResolver.cs" />
<Compile Include="Serialization\JsonArrayContract.cs" />
@@ -138,10 +142,12 @@
<Compile Include="Serialization\JsonObjectContract.cs" />
<Compile Include="Serialization\JsonProperty.cs" />
<Compile Include="Serialization\JsonPropertyCollection.cs" />
<Compile Include="Serialization\JsonSerializerInternalBase.cs" />
<Compile Include="Serialization\JsonSerializerInternalReader.cs" />
<Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonSerializerReader.cs" />
<Compile Include="Serialization\JsonSerializerWriter.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="TypeNameHandling.cs" />
<Compile Include="Utilities\BidirectionalDictionary.cs" />
<Compile Include="Utilities\ConvertUtils.cs" />
@@ -81,6 +81,9 @@
<Compile Include="Converters\CustomCreationConverter.cs" />
<Compile Include="Converters\EntityKeyMemberConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProvider.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptor.cs" />
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
<Compile Include="PreserveReferencesHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
@@ -139,6 +142,7 @@
<Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
<Compile Include="Serialization\DefaultContractResolver.cs" />
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
<Compile Include="Serialization\ErrorContext.cs" />
<Compile Include="Serialization\IContractResolver.cs" />
<Compile Include="Serialization\JsonArrayContract.cs" />
<Compile Include="Serialization\JsonContract.cs" />
@@ -155,11 +159,13 @@
<Compile Include="Serialization\IReferenceResolver.cs" />
<Compile Include="Schema\JsonSchemaType.cs" />
<Compile Include="Serialization\JsonObjectContract.cs" />
<Compile Include="Serialization\JsonSerializerInternalBase.cs" />
<Compile Include="Serialization\JsonSerializerInternalReader.cs" />
<Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonSerializerReader.cs" />
<Compile Include="Serialization\JsonSerializerWriter.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\CachedAttributeGetter.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="Utilities\ThreadSafeStore.cs" />
<Compile Include="TypeNameHandling.cs" />
<Compile Include="Utilities\BidirectionalDictionary.cs" />
@@ -82,6 +82,9 @@
<Compile Include="JsonValidatingReader.cs" />
<Compile Include="JsonWriter.cs" />
<Compile Include="JsonWriterException.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProvider.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptor.cs" />
<Compile Include="Linq\Extensions.cs" />
<Compile Include="Linq\IJEnumerable.cs" />
<Compile Include="Linq\JArray.cs" />
@@ -117,9 +120,10 @@
<Compile Include="Serialization\JsonObjectContract.cs" />
<Compile Include="Serialization\JsonProperty.cs" />
<Compile Include="Serialization\JsonPropertyCollection.cs" />
<Compile Include="Serialization\JsonSerializerInternalBase.cs" />
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonSerializerReader.cs" />
<Compile Include="Serialization\JsonSerializerWriter.cs" />
<Compile Include="Serialization\JsonSerializerInternalReader.cs" />
<Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
<Compile Include="TypeNameHandling.cs" />
<Compile Include="Utilities\BidirectionalDictionary.cs" />
<Compile Include="Utilities\CollectionUtils.cs" />
+8 -2
View File
@@ -90,6 +90,9 @@
<Compile Include="Converters\CustomCreationConverter.cs" />
<Compile Include="Converters\EntityKeyMemberConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptionProvider.cs" />
<Compile Include="Linq\ComponentModel\JTypeDescriptor.cs" />
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
<Compile Include="PreserveReferencesHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
@@ -148,6 +151,7 @@
<Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
<Compile Include="Serialization\DefaultContractResolver.cs" />
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
<Compile Include="Serialization\ErrorContext.cs" />
<Compile Include="Serialization\IContractResolver.cs" />
<Compile Include="Serialization\JsonArrayContract.cs" />
<Compile Include="Serialization\JsonContract.cs" />
@@ -164,11 +168,13 @@
<Compile Include="Serialization\IReferenceResolver.cs" />
<Compile Include="Schema\JsonSchemaType.cs" />
<Compile Include="Serialization\JsonObjectContract.cs" />
<Compile Include="Serialization\JsonSerializerInternalBase.cs" />
<Compile Include="Serialization\JsonSerializerInternalReader.cs" />
<Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonSerializerReader.cs" />
<Compile Include="Serialization\JsonSerializerWriter.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\CachedAttributeGetter.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="Utilities\ThreadSafeStore.cs" />
<Compile Include="TypeNameHandling.cs" />
<Compile Include="Utilities\BidirectionalDictionary.cs" />
@@ -183,6 +183,10 @@ namespace Newtonsoft.Json.Serialization
{
contract.OnDeserialized = method;
}
if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), contract.OnError, ref prevAttributeType))
{
contract.OnError = method;
}
}
#endif
}
@@ -249,8 +253,16 @@ namespace Newtonsoft.Json.Serialization
if (method.ReturnType != typeof(void))
throw new Exception("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method));
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext))
throw new Exception("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext)));
if (attributeType == typeof(OnErrorAttribute))
{
if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))
throw new Exception("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof (StreamingContext), typeof(ErrorContext)));
}
else
{
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext))
throw new Exception("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext)));
}
prevAttributeType = attributeType;
@@ -0,0 +1,68 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !PocketPC && !SILVERLIGHT && !NET20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Newtonsoft.Json.Serialization
{
/// <summary>
/// Provides information surrounding an error.
/// </summary>
public class ErrorContext
{
internal ErrorContext(object originalObject, object member, Exception error)
{
OriginalObject = originalObject;
Member = member;
Error = error;
}
/// <summary>
/// Gets or sets the error.
/// </summary>
/// <value>The error.</value>
public Exception Error { get; private set; }
/// <summary>
/// Gets the original object that caused the error.
/// </summary>
/// <value>The original object that caused the error.</value>
public object OriginalObject { get; private set; }
/// <summary>
/// Gets the member that caused the error.
/// </summary>
/// <value>The member that caused the error.</value>
public object Member { get; private set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ErrorContext"/> is handled.
/// </summary>
/// <value><c>true</c> if handled; otherwise, <c>false</c>.</value>
public bool Handled { get; set; }
}
}
#endif
@@ -47,7 +47,8 @@ namespace Newtonsoft.Json.Serialization
public bool? IsReference { get; set; }
#if !PocketPC && !SILVERLIGHT
private static readonly object[] SerializationEventParameterValues = new object[] { new StreamingContext(StreamingContextStates.All) };
private static readonly StreamingContext SerializationStreamingContextParameter = new StreamingContext(StreamingContextStates.All);
private static readonly object[] SerializationEventParameterValues = new object[] { SerializationStreamingContextParameter };
/// <summary>
/// Gets or sets the method called immediately after deserialization of the object.
@@ -69,6 +70,8 @@ namespace Newtonsoft.Json.Serialization
/// </summary>
/// <value>The method called before serialization of the object.</value>
public MethodInfo OnSerializing { get; set; }
public MethodInfo OnError { get; set; }
#endif
internal void InvokeOnSerializing(object o)
@@ -103,6 +106,14 @@ namespace Newtonsoft.Json.Serialization
#endif
}
#if !PocketPC && !SILVERLIGHT && !NET20
internal void InvokeOnError(object o, ErrorContext errorContext)
{
if (OnError != null && o == errorContext.OriginalObject)
OnError.Invoke(o, new object[] { SerializationStreamingContextParameter, errorContext });
}
#endif
internal JsonContract(Type underlyingType)
{
ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType");
@@ -0,0 +1,57 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Net;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Serialization
{
internal abstract class JsonSerializerInternalBase
{
#if !PocketPC && !SILVERLIGHT && !NET20
private ErrorContext _currentErrorContext;
protected ErrorContext GetErrorContext(object originalObject, object member, Exception error)
{
if (_currentErrorContext == null)
_currentErrorContext = new ErrorContext(originalObject, member, error);
if (_currentErrorContext.Error != error)
throw new InvalidOperationException("Current error context error is different to requested error.");
return _currentErrorContext;
}
protected void ClearErrorContext()
{
if (_currentErrorContext == null)
throw new InvalidOperationException("Could not clear error context. Error context is already null.");
_currentErrorContext = null;
}
#endif
}
}
@@ -35,12 +35,12 @@ using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Serialization
{
internal class JsonSerializerReader
internal class JsonSerializerInternalReader : JsonSerializerInternalBase
{
internal readonly JsonSerializer _serializer;
private JsonSerializerProxy _internalSerializer;
public JsonSerializerReader(JsonSerializer serializer)
public JsonSerializerInternalReader(JsonSerializer serializer)
{
ValidationUtils.ArgumentNotNull(serializer, "serializer");
@@ -79,7 +79,7 @@ namespace Newtonsoft.Json.Serialization
else if (contract is JsonObjectContract)
PopulateObject(target, reader, (JsonObjectContract) contract, id);
else
throw new Exception("dfsdfsdf");
throw new JsonSerializationException("Expected a JsonObjectContract or JsonDictionaryContract for type '{0}', got '{1}'.".FormatWith(CultureInfo.InvariantCulture, objectType, contract.GetType()));
}
}
@@ -292,17 +292,16 @@ namespace Newtonsoft.Json.Serialization
return PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(existingValue), reader, (JsonDictionaryContract) contract, id);
}
else if (contract is JsonObjectContract)
if (contract is JsonObjectContract)
{
if (existingValue == null)
return CreateAndPopulateObject(reader, (JsonObjectContract) contract, id);
return PopulateObject(existingValue, reader, (JsonObjectContract) contract, id);
}
else
{
throw new JsonSerializationException("Expected a JsonObjectContract or JsonDictionaryContract for type '{0}', got '{1}'.".FormatWith(CultureInfo.InvariantCulture, objectType, contract.GetType()));
}
throw new JsonSerializationException("Expected a JsonObjectContract or JsonDictionaryContract for type '{0}', got '{1}'.".FormatWith(CultureInfo.InvariantCulture, objectType, contract.GetType()));
}
private JsonArrayContract GetArrayContract(Type objectType)
@@ -400,7 +399,8 @@ namespace Newtonsoft.Json.Serialization
bool useExistingValue = false;
if ((_serializer.ObjectCreationHandling == ObjectCreationHandling.Auto || _serializer.ObjectCreationHandling == ObjectCreationHandling.Reuse)
&& (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject))
&& (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)
&& property.Readable)
{
currentValue = ReflectionUtils.GetMemberValue(property.Member, target);
@@ -457,7 +457,22 @@ namespace Newtonsoft.Json.Serialization
object keyValue = EnsureType(reader.Value, contract.DictionaryKeyType);
CheckedRead(reader);
dictionary.Add(keyValue, CreateValue(reader, contract.DictionaryValueType, null, null));
try
{
dictionary.Add(keyValue, CreateValue(reader, contract.DictionaryValueType, null, null));
}
catch (Exception ex)
{
#if !PocketPC && !SILVERLIGHT && !NET20
ErrorContext errorContext = GetErrorContext(dictionary.UnderlyingDictionary, keyValue, ex);
contract.InvokeOnError(dictionary.UnderlyingDictionary, errorContext);
if (errorContext.Handled)
ClearErrorContext();
else
#endif
throw;
}
break;
case JsonToken.EndObject:
contract.InvokeOnDeserialized(dictionary.UnderlyingDictionary);
@@ -481,6 +496,8 @@ namespace Newtonsoft.Json.Serialization
#if !PocketPC && !SILVERLIGHT
if (contract.OnSerializing != null && isTemporaryListReference)
throw new JsonSerializationException("Cannot call OnSerializing on an array or readonly list: {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.OnError != null && isTemporaryListReference)
throw new JsonSerializationException("Cannot call OnError on an array or readonly list: {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
#endif
PopulateList(l, reader, reference, contract);
@@ -505,9 +522,24 @@ namespace Newtonsoft.Json.Serialization
case JsonToken.Comment:
break;
default:
object value = CreateValue(reader, contract.CollectionItemType, null, null);
try
{
object value = CreateValue(reader, contract.CollectionItemType, null, null);
list.Add(value);
list.Add(value);
}
catch (Exception ex)
{
#if !PocketPC && !SILVERLIGHT && !NET20
ErrorContext errorContext = GetErrorContext(list, list.Count, ex);
contract.InvokeOnError(list, errorContext);
if (errorContext.Handled)
ClearErrorContext();
else
#endif
throw;
}
break;
}
}
@@ -537,11 +569,15 @@ namespace Newtonsoft.Json.Serialization
{
Type objectType = contract.UnderlyingType;
// object should have a single constructor
ConstructorInfo c = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).SingleOrDefault();
ConstructorInfo[] constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
if (c == null)
if (constructors.Length == 0)
throw new JsonSerializationException("Could not find a public constructor for type {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
if (constructors.Length > 1)
throw new JsonSerializationException("Unable to determine which constructor to use for type {0}. A class with no default constructor should have only one constructor with arguments.".FormatWith(CultureInfo.InvariantCulture, objectType));
// object should have a single constructor
ConstructorInfo c = constructors[0];
// create a dictionary to put retrieved values into
IDictionary<JsonProperty, object> propertyValues = contract.Properties.Where(p => !p.Ignored).ToDictionary(kv => kv, kv => (object)null);
@@ -631,8 +667,23 @@ namespace Newtonsoft.Json.Serialization
if (reader.TokenType != JsonToken.Null)
SetRequiredProperty(memberName, requiredProperties);
SetObjectMember(reader, newObject, contract, memberName);
try
{
SetObjectMember(reader, newObject, contract, memberName);
}
catch (Exception ex)
{
#if !PocketPC && !SILVERLIGHT && !NET20
ErrorContext errorContext = GetErrorContext(newObject, memberName, ex);
contract.InvokeOnError(newObject, errorContext);
if (errorContext.Handled)
ClearErrorContext();
else
#endif
throw;
}
break;
case JsonToken.EndObject:
foreach (KeyValuePair<string, bool> requiredProperty in requiredProperties)
@@ -36,12 +36,12 @@ using System.Runtime.Serialization;
namespace Newtonsoft.Json.Serialization
{
internal class JsonSerializerWriter
internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
{
internal readonly JsonSerializer _serializer;
private JsonSerializerProxy _internalSerializer;
private List<object> _serializeStack;
private List<object> SerializeStack
{
get
@@ -53,7 +53,7 @@ namespace Newtonsoft.Json.Serialization
}
}
public JsonSerializerWriter(JsonSerializer serializer)
public JsonSerializerInternalWriter(JsonSerializer serializer)
{
ValidationUtils.ArgumentNotNull(serializer, "serializer");
@@ -287,8 +287,23 @@ namespace Newtonsoft.Json.Serialization
foreach (JsonProperty property in contract.Properties)
{
if (!property.Ignored && property.Readable)
WriteMemberInfoProperty(writer, value, property);
try
{
if (!property.Ignored && property.Readable)
WriteMemberInfoProperty(writer, value, property);
}
catch (Exception ex)
{
#if !PocketPC && !SILVERLIGHT && !NET20
ErrorContext errorContext = GetErrorContext(value, property.Member.Name, ex);
contract.InvokeOnError(value, errorContext);
if (errorContext.Handled)
ClearErrorContext();
else
#endif
throw;
}
}
writer.WriteEndObject();
@@ -366,18 +381,33 @@ namespace Newtonsoft.Json.Serialization
for (int i = 0; i < values.Count; i++)
{
object value = values[i];
if (ShouldWriteReference(value, null))
try
{
WriteReference(writer, value);
object value = values[i];
if (ShouldWriteReference(value, null))
{
WriteReference(writer, value);
}
else
{
if (!CheckForCircularReference(value, null))
continue;
SerializeValue(writer, value, null);
}
}
else
catch (Exception ex)
{
if (!CheckForCircularReference(value, null))
continue;
#if !PocketPC && !SILVERLIGHT && !NET20
ErrorContext errorContext = GetErrorContext(values, i, ex);
contract.InvokeOnError(values, errorContext);
SerializeValue(writer, value, null);
if (errorContext.Handled)
ClearErrorContext();
else
#endif
throw;
}
}
@@ -414,20 +444,37 @@ namespace Newtonsoft.Json.Serialization
foreach (DictionaryEntry entry in values)
{
string propertyName = entry.Key.ToString();
object value = entry.Value;
if (ShouldWriteReference(value, null))
try
{
writer.WritePropertyName(propertyName);
WriteReference(writer, value);
object value = entry.Value;
if (ShouldWriteReference(value, null))
{
writer.WritePropertyName(propertyName);
WriteReference(writer, value);
}
else
{
if (!CheckForCircularReference(value, null))
continue;
writer.WritePropertyName(propertyName);
SerializeValue(writer, value, null);
}
}
else
catch (Exception ex)
{
if (!CheckForCircularReference(value, null))
continue;
#if !PocketPC && !SILVERLIGHT && !NET20
ErrorContext errorContext = GetErrorContext(values, propertyName, ex);
contract.InvokeOnError(values, errorContext);
writer.WritePropertyName(propertyName);
SerializeValue(writer, value, null);
if (errorContext.Handled)
ClearErrorContext();
else
#endif
throw;
}
}
@@ -31,8 +31,8 @@ namespace Newtonsoft.Json.Serialization
{
internal class JsonSerializerProxy : JsonSerializer
{
private readonly JsonSerializerReader _serializerReader;
private readonly JsonSerializerWriter _serializerWriter;
private readonly JsonSerializerInternalReader _serializerReader;
private readonly JsonSerializerInternalWriter _serializerWriter;
private readonly JsonSerializer _serializer;
public override IReferenceResolver ReferenceResolver
@@ -100,7 +100,7 @@ namespace Newtonsoft.Json.Serialization
set { _serializer.Binder = value; }
}
public JsonSerializerProxy(JsonSerializerReader serializerReader)
public JsonSerializerProxy(JsonSerializerInternalReader serializerReader)
{
ValidationUtils.ArgumentNotNull(serializerReader, "serializerReader");
@@ -108,7 +108,7 @@ namespace Newtonsoft.Json.Serialization
_serializer = serializerReader._serializer;
}
public JsonSerializerProxy(JsonSerializerWriter serializerWriter)
public JsonSerializerProxy(JsonSerializerInternalWriter serializerWriter)
{
ValidationUtils.ArgumentNotNull(serializerWriter, "serializerWriter");
@@ -0,0 +1,39 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !PocketPC && !SILVERLIGHT && !NET20
using System;
namespace Newtonsoft.Json.Serialization
{
/// <summary>
/// When applied to a method, specifies that the method is called when an error occurs serializing an object.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class OnErrorAttribute : Attribute
{
}
}
#endif