From 3ae2accce4972e77022fdf8f60e7c6ebc78d6362 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Sun, 20 Sep 2009 09:50:35 +0000 Subject: [PATCH] -More error handling work --- .../SerializationEventAttributeTests.cs | 131 +++++++++++++++++- Src/Newtonsoft.Json/JsonWriter.cs | 2 +- .../Serialization/JsonContract.cs | 2 +- .../JsonSerializerInternalReader.cs | 22 ++- .../JsonSerializerInternalWriter.cs | 24 +++- 5 files changed, 166 insertions(+), 15 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs index 61dec3e4..3acaf37a 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs @@ -38,6 +38,7 @@ using Newtonsoft.Json.Tests.TestObjects; using NUnit.Framework; using Newtonsoft.Json.Linq; using System.Collections; +using Newtonsoft.Json.Converters; namespace Newtonsoft.Json.Tests.Serialization { @@ -115,11 +116,31 @@ namespace Newtonsoft.Json.Tests.Serialization public class ListErrorObject { - public string Member + public string Member { get; set; } + + private string _throwError; + public string ThrowError { - get { throw new Exception("ListErrorObject.Member get error!"); } - set { throw new Exception("ListErrorObject.Member set error!"); } + get + { + if (_throwError != null) + return _throwError; + + throw new Exception("ListErrorObject.ThrowError get error!"); + } + set + { + if (value != null && value.StartsWith("Handle")) + { + _throwError = value; + return; + } + + throw new Exception("ListErrorObject.ThrowError set error!"); + } } + + public string Member2 { get; set; } } public class ListErrorObjectCollection : Collection @@ -131,6 +152,15 @@ namespace Newtonsoft.Json.Tests.Serialization } } + public class DateTimeErrorObjectCollection : Collection + { + [OnError] + internal void OnErrorMethod(StreamingContext context, ErrorContext errorContext) + { + errorContext.Handled = true; + } + } + public class VersionKeyedCollection : KeyedCollection, IList { public List Messages { get; set; } @@ -237,10 +267,99 @@ namespace Newtonsoft.Json.Tests.Serialization } [Test] - [ExpectedException(typeof(TargetInvocationException))] - public void ErrorInChild() + public void DeserializingErrorInChildObject() { - JsonConvert.DeserializeObject(@"[{""Member"":""Value""}]"); + ListErrorObjectCollection c = JsonConvert.DeserializeObject(@"[ + { + ""Member"": ""Value1"", + ""Member2"": null + }, + { + ""Member"": ""Value2"" + }, + { + ""ThrowError"": ""Value"", + ""Object"": { + ""Array"": [ + 1, + 2 + ] + } + }, + { + ""ThrowError"": ""Handle this!"", + ""Member"": ""Value3"" + } +]"); + + Assert.AreEqual(3, c.Count); + Assert.AreEqual("Value1", c[0].Member); + Assert.AreEqual("Value2", c[1].Member); + Assert.AreEqual("Value3", c[2].Member); + Assert.AreEqual("Handle this!", c[2].ThrowError); + } + + [Test] + public void SerializingErrorInChildObject() + { + ListErrorObjectCollection c = new ListErrorObjectCollection + { + new ListErrorObject + { + Member = "Value1", + ThrowError = "Handle this!", + Member2 = "Member1" + }, + new ListErrorObject + { + Member = "Value2", + Member2 = "Member2" + }, + new ListErrorObject + { + Member = "Value3", + ThrowError = "Handle that!", + Member2 = "Member3" + } + }; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"[ + { + ""Member"": ""Value1"", + ""ThrowError"": ""Handle this!"", + ""Member2"": ""Member1"" + }, + { + ""Member"": ""Value2"" + }, + { + ""Member"": ""Value3"", + ""ThrowError"": ""Handle that!"", + ""Member2"": ""Member3"" + } +]", json); + } + + [Test] + public void DeserializingErrorInDateTimeCollection() + { + DateTimeErrorObjectCollection c = JsonConvert.DeserializeObject(@"[ + ""2009-09-09T00:00:00Z"", + ""kjhkjhkjhkjh"", + [ + 1 + ], + ""1977-02-20T00:00:00Z"", + null, + ""2000-12-01T00:00:00Z"" +]", new IsoDateTimeConverter()); + + Assert.AreEqual(3, c.Count); + Assert.AreEqual(new DateTime(2009, 9, 9, 0, 0, 0, DateTimeKind.Utc), c[0]); + Assert.AreEqual(new DateTime(1977, 2, 20, 0, 0, 0, DateTimeKind.Utc), c[1]); + Assert.AreEqual(new DateTime(2000, 12, 1, 0, 0, 0, DateTimeKind.Utc), c[2]); } [Test] diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index f934f824..e7738d7d 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -129,7 +129,7 @@ namespace Newtonsoft.Json /// Gets the top. /// /// The top. - protected int Top + protected internal int Top { get { return _top; } } diff --git a/Src/Newtonsoft.Json/Serialization/JsonContract.cs b/Src/Newtonsoft.Json/Serialization/JsonContract.cs index f02984df..be3a42f6 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonContract.cs @@ -109,7 +109,7 @@ namespace Newtonsoft.Json.Serialization #if !PocketPC && !SILVERLIGHT && !NET20 internal void InvokeOnError(object o, ErrorContext errorContext) { - if (OnError != null && o == errorContext.OriginalObject) + if (OnError != null) OnError.Invoke(o, new object[] { SerializationStreamingContextParameter, errorContext }); } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index a665c0fb..0fee2dcf 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -449,6 +449,8 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnDeserializing(dictionary.UnderlyingDictionary); + int initialDepth = reader.Depth; + do { switch (reader.TokenType) @@ -468,7 +470,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnError(dictionary.UnderlyingDictionary, errorContext); if (errorContext.Handled) - ClearErrorContext(); + HandleError(reader, initialDepth); else #endif throw; @@ -511,6 +513,8 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnDeserializing(list); + int initialDepth = reader.Depth; + while (reader.Read()) { switch (reader.TokenType) @@ -535,7 +539,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnError(list, errorContext); if (errorContext.Handled) - ClearErrorContext(); + HandleError(reader, initialDepth); else #endif throw; @@ -655,6 +659,8 @@ namespace Newtonsoft.Json.Serialization if (id != null) _serializer.ReferenceResolver.AddReference(id, newObject); + int initialDepth = reader.Depth; + do { switch (reader.TokenType) @@ -679,7 +685,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnError(newObject, errorContext); if (errorContext.Handled) - ClearErrorContext(); + HandleError(reader, initialDepth); else #endif throw; @@ -725,5 +731,15 @@ namespace Newtonsoft.Json.Serialization } } } + + private void HandleError(JsonReader reader, int initialDepth) + { + ClearErrorContext(); + + while (reader.Depth > (initialDepth + 1)) + { + reader.Read(); + } + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 34e9d330..a03c7556 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -285,6 +285,8 @@ namespace Newtonsoft.Json.Serialization WriteTypeProperty(writer, contract.UnderlyingType); } + int initialDepth = writer.Top; + foreach (JsonProperty property in contract.Properties) { try @@ -299,7 +301,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnError(value, errorContext); if (errorContext.Handled) - ClearErrorContext(); + HandleError(writer, initialDepth); else #endif throw; @@ -379,6 +381,8 @@ namespace Newtonsoft.Json.Serialization writer.WriteStartArray(); + int initialDepth = writer.Top; + for (int i = 0; i < values.Count; i++) { try @@ -404,7 +408,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnError(values, errorContext); if (errorContext.Handled) - ClearErrorContext(); + HandleError(writer, initialDepth); else #endif throw; @@ -441,6 +445,8 @@ namespace Newtonsoft.Json.Serialization WriteTypeProperty(writer, values.GetType()); } + int initialDepth = writer.Top; + foreach (DictionaryEntry entry in values) { string propertyName = entry.Key.ToString(); @@ -471,7 +477,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnError(values, errorContext); if (errorContext.Handled) - ClearErrorContext(); + HandleError(writer, initialDepth); else #endif throw; @@ -483,5 +489,15 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerialized(values); } + + private void HandleError(JsonWriter writer, int initialDepth) + { + ClearErrorContext(); + + while (writer.Top > initialDepth) + { + writer.WriteEnd(); + } + } } } \ No newline at end of file