-Fixed error when wrapping an exception in a JsonConverter

This commit is contained in:
James Newton-King
2013-12-23 22:42:38 +13:00
parent d529190b46
commit 40c24307de
8 changed files with 186 additions and 6 deletions
@@ -75,4 +75,4 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("5.0.8.16815")]
[assembly: AssemblyFileVersion("5.0.8.16823")]
@@ -4257,7 +4257,7 @@ To fix this error either change the environment to be fully trusted, change the
#if !NET20
dateTimeOffsetText = @"2000-12-20T22:59:59+02:00";
#else
dateTimeOffsetText = @"12/20/2000 22:59:59 +02:00";
dateTimeOffsetText = @"12/20/2000 22:59:59 +02:00";
#endif
ISerializableTestObject o = new ISerializableTestObject("String!", int.MinValue, dateTimeOffset, person);
@@ -715,6 +715,157 @@ namespace Newtonsoft.Json.Tests.Serialization
@"Unterminated string. Expected delimiter: "". Path '', line 1, position 3.",
() => { ErrorTestObject obj = s.Deserialize<ErrorTestObject>(jReader); });
}
public class RootThing
{
public Something Something { get; set; }
}
public class RootSomethingElse
{
public SomethingElse SomethingElse { get; set; }
}
/// <summary>
/// This could be an object we are passing up in an interface.
/// </summary>
[JsonConverter(typeof(SomethingConverter))]
public class Something
{
public class SomethingConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
// Do own stuff.
// Then call deserialise for inner object.
var innerObject = serializer.Deserialize(reader, typeof(SomethingElse));
return null;
}
catch (Exception ex)
{
// If we get an error wrap it in something less scary.
throw new Exception("An error occurred.", ex);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
try
{
Something s = (Something)value;
// Do own stuff.
// Then call serialise for inner object.
serializer.Serialize(writer, s.RootSomethingElse);
}
catch (Exception ex)
{
// If we get an error wrap it in something less scary.
throw new Exception("An error occurred.", ex);
}
}
}
public RootSomethingElse RootSomethingElse { get; set; }
public Something()
{
this.RootSomethingElse = new RootSomethingElse();
}
}
/// <summary>
/// This is an object that is contained in the interface object.
/// </summary>
[JsonConverter(typeof(SomethingElseConverter))]
public class SomethingElse
{
public class SomethingElseConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}
[Test]
public void DeserializeWrappingErrorsAndErrorHandling()
{
var serialiser = JsonSerializer.Create(new JsonSerializerSettings() { });
string foo = "{ something: { rootSomethingElse { somethingElse: 0 } } }";
var reader = new System.IO.StringReader(foo);
ExceptionAssert.Throws<Exception>(
"An error occurred.",
() => { serialiser.Deserialize(reader, typeof(Something)); });
}
[Test]
public void SerializeWrappingErrorsAndErrorHandling()
{
var serialiser = JsonSerializer.Create(new JsonSerializerSettings() { });
Something s = new Something
{
RootSomethingElse = new RootSomethingElse
{
SomethingElse = new SomethingElse()
}
};
RootThing r = new RootThing
{
Something = s
};
var writer = new System.IO.StringWriter();
ExceptionAssert.Throws<Exception>(
"An error occurred.",
() => { serialiser.Serialize(writer, r); });
}
[Test]
public void DeserializeRootConverter()
{
SomethingElse result = JsonConvert.DeserializeObject<SomethingElse>("{}", new JsonSerializerSettings
{
Error = (o, e) => { e.ErrorContext.Handled = true; }
});
Assert.IsNull(result);
}
[Test]
public void SerializeRootConverter()
{
string result = JsonConvert.SerializeObject(new SomethingElse(), new JsonSerializerSettings
{
Error = (o, e) => { e.ErrorContext.Handled = true; }
});
Assert.AreEqual(string.Empty, result);
}
}
internal interface IErrorPerson2
@@ -1,6 +1,10 @@
using System.Collections.Generic;
using System.Globalization;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
@@ -30,7 +34,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
else
{
if (errorWhenNoMatch)
throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select(n => "'" + n + "'")), t.GetType().Name));
throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select(n => "'" + n + "'").ToArray()), t.GetType().Name));
}
}
}
@@ -91,5 +91,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("5.0.8.16815")]
[assembly: AssemblyFileVersion("5.0.8.16823")]
[assembly: CLSCompliant(true)]
@@ -43,7 +43,7 @@ namespace Newtonsoft.Json.Serialization
internal bool Traced { get; set; }
/// <summary>
/// Gets or sets the error.
/// Gets the error.
/// </summary>
/// <value>The error.</value>
public Exception Error { get; private set; }
@@ -174,6 +174,10 @@ namespace Newtonsoft.Json.Serialization
}
else
{
// clear context in case serializer is being used inside a converter
// if the converter wraps the error then not clearing the context will cause this error:
// "Current error context error is different to requested error."
ClearErrorContext();
throw;
}
}
@@ -65,7 +65,28 @@ namespace Newtonsoft.Json.Serialization
if (objectType != null)
_rootContract = Serializer._contractResolver.ResolveContract(objectType);
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null);
JsonContract contract = GetContractSafe(value);
try
{
SerializeValue(jsonWriter, value, contract, null, null, null);
}
catch (Exception ex)
{
if (IsErrorHandled(null, contract, null, null, jsonWriter.Path, ex))
{
HandleError(jsonWriter, 0);
}
else
{
// clear context in case serializer is being used inside a converter
// if the converter wraps the error then not clearing the context will cause this error:
// "Current error context error is different to requested error."
ClearErrorContext();
throw;
}
}
}
private JsonSerializerProxy GetInternalSerializer()