-Changed serialization callbacks on JsonContract to delegates

-Added Obsolete attributes to old serialization methods on JsonContract
-Added VS and ReSharper settings files
-Fixed converting null JSON value to XML
-Fixed tests
This commit is contained in:
James Newton-King
2013-03-17 14:25:01 +13:00
parent 1356c31670
commit e857e48564
13 changed files with 182 additions and 112 deletions
@@ -711,7 +711,7 @@ namespace Newtonsoft.Json.Tests.Bson
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Bytes, reader.TokenType);
Assert.AreEqual(new byte[] { 246, 255, 255, 255, 255, 255, 255, 31, 178, 33, 203, 40, 89, 132, 196, 174, 3, 138, 68, 52, 47, 76, 78, 158, 62, 1 }, reader.Value);
CollectionAssert.AreEqual(new byte[] { 246, 255, 255, 255, 255, 255, 255, 31, 178, 33, 203, 40, 89, 132, 196, 174, 3, 138, 68, 52, 47, 76, 78, 158, 62, 1 }, (byte[])reader.Value);
Assert.AreEqual(i, new BigInteger((byte[])reader.Value));
Assert.IsTrue(reader.Read());
@@ -1902,6 +1902,27 @@ namespace Newtonsoft.Json.Tests.Converters
Assert.AreEqual(@"{""root"":{""@xmlns"":""http://www.example.com/ns"",""a"":null,""bns:b"":{""@xmlns:bns"":""http://www.example.com/ns""},""c"":null}}", json2);
#endif
}
#if !NET20
class NullableXml
{
public string Name;
public XElement notNull;
public XElement isNull;
}
[Test]
public void SerializeAndDeserializeNullableXml()
{
var xml = new NullableXml { Name = "test", notNull = XElement.Parse("<root>test</root>") };
var json = JsonConvert.SerializeObject(xml);
var w2 = JsonConvert.DeserializeObject<NullableXml>(json);
Assert.AreEqual(xml.Name, w2.Name);
Assert.AreEqual(xml.isNull, w2.isNull);
Assert.AreEqual(xml.notNull.ToString(), w2.notNull.ToString());
}
#endif
}
}
#endif
@@ -368,7 +368,7 @@ namespace Newtonsoft.Json.Tests.Linq
Assert.AreEqual("9223372036854775807", (string)(new JValue(new BigInteger(long.MaxValue))));
intData = (byte[]) (new JValue(new BigInteger(long.MaxValue)));
Assert.AreEqual(new byte[] { 255, 255, 255, 255, 255, 255, 255, 127 }, intData);
CollectionAssert.AreEqual(new byte[] { 255, 255, 255, 255, 255, 255, 255, 127 }, intData);
#endif
}
@@ -75,4 +75,4 @@ using System.Security;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("5.0.1.15916")]
[assembly: AssemblyFileVersion("5.0.1.15917")]
+5
View File
@@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">False</s:Boolean>
</wpf:ResourceDictionary>
+13
View File
@@ -0,0 +1,13 @@
<UserSettings>
<ApplicationIdentity version="11.0"/>
<ToolsOptions>
<ToolsOptionsCategory name="TextEditor" RegisteredName="TextEditor">
<ToolsOptionsSubCategory name="CSharp" RegisteredName="CSharp" PackageName="Text Management Package">
<PropertyValue name="TabSize">2</PropertyValue>
<PropertyValue name="IndentStyle">2</PropertyValue>
<PropertyValue name="InsertTabs">false</PropertyValue>
<PropertyValue name="IndentSize">2</PropertyValue>
</ToolsOptionsSubCategory>
</ToolsOptionsCategory>
</ToolsOptions>
</UserSettings>
@@ -1082,6 +1082,9 @@ namespace Newtonsoft.Json.Converters
/// <returns>The object value.</returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
IXmlDocument document = null;
IXmlNode rootNode = null;
@@ -90,6 +90,6 @@ using System.Security;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("5.0.1.15916")]
[assembly: AssemblyFileVersion("5.0.1.15917")]
[assembly: CLSCompliant(true)]
@@ -547,11 +547,11 @@ namespace Newtonsoft.Json.Serialization
private void ResolveCallbackMethods(JsonContract contract, Type t)
{
List<MethodInfo> onSerializing;
List<MethodInfo> onSerialized;
List<MethodInfo> onDeserializing;
List<MethodInfo> onDeserialized;
List<MethodInfo> onError;
List<SerializationCallback> onSerializing;
List<SerializationCallback> onSerialized;
List<SerializationCallback> onDeserializing;
List<SerializationCallback> onDeserialized;
List<SerializationErrorCallback> onError;
GetCallbackMethodsForType(t, out onSerializing, out onSerialized, out onDeserializing, out onDeserialized, out onError);
@@ -559,34 +559,34 @@ namespace Newtonsoft.Json.Serialization
{
#if NETFX_CORE
if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
contract.OnSerializingMethods.AddRange(onSerializing);
contract.OnSerializingCallbacks.AddRange(onSerializing);
#else
contract.OnSerializingMethods.AddRange(onSerializing);
contract.OnSerializingCallbacks.AddRange(onSerializing);
#endif
}
if (onSerialized != null)
contract.OnSerializedMethods.AddRange(onSerialized);
contract.OnSerializedCallbacks.AddRange(onSerialized);
if (onDeserializing != null)
contract.OnDeserializingMethods.AddRange(onDeserializing);
contract.OnDeserializingCallbacks.AddRange(onDeserializing);
if (onDeserialized != null)
{
// ConcurrentDictionary throws an error here so don't use its OnDeserialized - http://json.codeplex.com/discussions/257093
#if !(NET35 || NET20 || SILVERLIGHT || WINDOWS_PHONE || PORTABLE)
if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
contract.OnDeserializedMethods.AddRange(onDeserialized);
contract.OnDeserializedCallbacks.AddRange(onDeserialized);
#else
contract.OnDeserializedMethods.AddRange(onDeserialized);
contract.OnDeserializedCallbacks.AddRange(onDeserialized);
#endif
}
if (onError != null)
contract.OnErrorMethods.AddRange(onError);
contract.OnErrorCallbacks.AddRange(onError);
}
private void GetCallbackMethodsForType(Type type, out List<MethodInfo> onSerializing, out List<MethodInfo> onSerialized, out List<MethodInfo> onDeserializing, out List<MethodInfo> onDeserialized, out List<MethodInfo> onError)
private void GetCallbackMethodsForType(Type type, out List<SerializationCallback> onSerializing, out List<SerializationCallback> onSerialized, out List<SerializationCallback> onDeserializing, out List<SerializationCallback> onDeserialized, out List<SerializationErrorCallback> onError)
{
onSerializing = null;
onSerialized = null;
@@ -616,32 +616,32 @@ namespace Newtonsoft.Json.Serialization
if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), currentOnSerializing, ref prevAttributeType))
{
onSerializing = onSerializing ?? new List<MethodInfo>();
onSerializing.Add(method);
onSerializing = onSerializing ?? new List<SerializationCallback>();
onSerializing.Add(JsonContract.CreateSerializationCallback(method));
currentOnSerializing = method;
}
if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), currentOnSerialized, ref prevAttributeType))
{
onSerialized = onSerialized ?? new List<MethodInfo>();
onSerialized.Add(method);
onSerialized = onSerialized ?? new List<SerializationCallback>();
onSerialized.Add(JsonContract.CreateSerializationCallback(method));
currentOnSerialized = method;
}
if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), currentOnDeserializing, ref prevAttributeType))
{
onDeserializing = onDeserializing ?? new List<MethodInfo>();
onDeserializing.Add(method);
onDeserializing = onDeserializing ?? new List<SerializationCallback>();
onDeserializing.Add(JsonContract.CreateSerializationCallback(method));
currentOnDeserializing = method;
}
if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), currentOnDeserialized, ref prevAttributeType))
{
onDeserialized = onDeserialized ?? new List<MethodInfo>();
onDeserialized.Add(method);
onDeserialized = onDeserialized ?? new List<SerializationCallback>();
onDeserialized.Add(JsonContract.CreateSerializationCallback(method));
currentOnDeserialized = method;
}
if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), currentOnError, ref prevAttributeType))
{
onError = onError ?? new List<MethodInfo>();
onError.Add(method);
onError = onError ?? new List<SerializationErrorCallback>();
onError.Add(JsonContract.CreateSerializationErrorCallback(method));
currentOnError = method;
}
}
+101 -82
View File
@@ -51,6 +51,10 @@ namespace Newtonsoft.Json.Serialization
Linq
}
public delegate void SerializationCallback(object o, StreamingContext context);
public delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext);
/// <summary>
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
/// </summary>
@@ -94,37 +98,44 @@ namespace Newtonsoft.Json.Serialization
/// Gets or sets all methods called immediately after deserialization of the object.
/// </summary>
/// <value>The methods called immediately after deserialization of the object.</value>
public IList<MethodInfo> OnDeserializedMethods { get; private set; }
public IList<SerializationCallback> OnDeserializedCallbacks { get; private set; }
/// <summary>
/// Gets or sets all methods called during deserialization of the object.
/// </summary>
/// <value>The methods called during deserialization of the object.</value>
public IList<MethodInfo> OnDeserializingMethods { get; private set; }
public IList<SerializationCallback> OnDeserializingCallbacks { get; private set; }
/// <summary>
/// Gets or sets all methods called after serialization of the object graph.
/// </summary>
/// <value>The methods called after serialization of the object graph.</value>
public IList<MethodInfo> OnSerializedMethods { get; private set; }
public IList<SerializationCallback> OnSerializedCallbacks { get; private set; }
/// <summary>
/// Gets or sets all methods called before serialization of the object.
/// </summary>
/// <value>The methods called before serialization of the object.</value>
public IList<MethodInfo> OnSerializingMethods { get; private set; }
public IList<SerializationCallback> OnSerializingCallbacks { get; private set; }
/// <summary>
/// Gets or sets all method called when an error is thrown during the serialization of the object.
/// </summary>
/// <value>The methods called when an error is thrown during the serialization of the object.</value>
public IList<SerializationErrorCallback> OnErrorCallbacks { get; private set; }
/// <summary>
/// Gets or sets the method called immediately after deserialization of the object.
/// </summary>
/// <value>The method called immediately after deserialization of the object.</value>
[Obsolete("This property is obsolete and has been replaced by the OnDeserializedCallbacks collection.")]
public MethodInfo OnDeserialized
{
get { return (OnDeserializedMethods.Count > 0) ? OnDeserializedMethods[0] : null; }
set
get { return (OnDeserializedCallbacks.Count > 0) ? OnDeserializedCallbacks[0].Method() : null; }
set
{
OnDeserializedMethods.Clear();
OnDeserializedMethods.Add(value);
OnDeserializedCallbacks.Clear();
OnDeserializedCallbacks.Add(CreateSerializationCallback(value));
}
}
@@ -132,13 +143,14 @@ namespace Newtonsoft.Json.Serialization
/// Gets or sets the method called during deserialization of the object.
/// </summary>
/// <value>The method called during deserialization of the object.</value>
[Obsolete("This property is obsolete and has been replaced by the OnDeserializingCallbacks collection.")]
public MethodInfo OnDeserializing
{
get { return (OnDeserializingMethods.Count > 0) ? OnDeserializingMethods[0] : null; }
get { return (OnDeserializingCallbacks.Count > 0) ? OnDeserializingCallbacks[0].Method() : null; }
set
{
OnDeserializingMethods.Clear();
OnDeserializingMethods.Add(value);
OnDeserializingCallbacks.Clear();
OnDeserializingCallbacks.Add(CreateSerializationCallback(value));
}
}
@@ -146,13 +158,14 @@ namespace Newtonsoft.Json.Serialization
/// Gets or sets the method called after serialization of the object graph.
/// </summary>
/// <value>The method called after serialization of the object graph.</value>
[Obsolete("This property is obsolete and has been replaced by the OnSerializedCallbacks collection.")]
public MethodInfo OnSerialized
{
get { return (OnSerializedMethods.Count > 0) ? OnSerializedMethods[0] : null; }
get { return (OnSerializedCallbacks.Count > 0) ? OnSerializedCallbacks[0].Method() : null; }
set
{
OnSerializedMethods.Clear();
OnSerializedMethods.Add(value);
OnSerializedCallbacks.Clear();
OnSerializedCallbacks.Add(CreateSerializationCallback(value));
}
}
@@ -160,13 +173,29 @@ namespace Newtonsoft.Json.Serialization
/// Gets or sets the method called before serialization of the object.
/// </summary>
/// <value>The method called before serialization of the object.</value>
[Obsolete("This property is obsolete and has been replaced by the OnSerializingCallbacks collection.")]
public MethodInfo OnSerializing
{
get { return (OnSerializingMethods.Count > 0) ? OnSerializingMethods[0] : null; }
get { return (OnSerializingCallbacks.Count > 0) ? OnSerializingCallbacks[0].Method() : null; }
set
{
OnSerializingMethods.Clear();
OnSerializingMethods.Add(value);
OnSerializingCallbacks.Clear();
OnSerializingCallbacks.Add(CreateSerializationCallback(value));
}
}
/// <summary>
/// Gets or sets the method called when an error is thrown during the serialization of the object.
/// </summary>
/// <value>The method called when an error is thrown during the serialization of the object.</value>
[Obsolete("This property is obsolete and has been replaced by the OnErrorCallbacks collection.")]
public MethodInfo OnError
{
get { return (OnErrorCallbacks.Count > 0) ? OnErrorCallbacks[0].Method() : null; }
set
{
OnErrorCallbacks.Clear();
OnErrorCallbacks.Add(CreateSerializationErrorCallback(value));
}
}
@@ -182,66 +211,6 @@ namespace Newtonsoft.Json.Serialization
/// <value><c>true</c> if the default object creator is non-public; otherwise, <c>false</c>.</value>
public bool DefaultCreatorNonPublic { get; set; }
/// <summary>
/// Gets or sets all method called when an error is thrown during the serialization of the object.
/// </summary>
/// <value>The methods called when an error is thrown during the serialization of the object.</value>
public IList<MethodInfo> OnErrorMethods { get; private set; }
/// <summary>
/// Gets or sets the method called when an error is thrown during the serialization of the object.
/// </summary>
/// <value>The method called when an error is thrown during the serialization of the object.</value>
public MethodInfo OnError
{
get { return (OnErrorMethods.Count > 0) ? OnErrorMethods[0] : null; }
set
{
OnErrorMethods.Clear();
OnErrorMethods.Add(value);
}
}
internal void InvokeOnSerializing(object o, StreamingContext context)
{
foreach (MethodInfo mi in OnSerializingMethods)
{
mi.Invoke(o, new object[] {context});
}
}
internal void InvokeOnSerialized(object o, StreamingContext context)
{
foreach (MethodInfo mi in OnSerializedMethods)
{
mi.Invoke(o, new object[] {context});
}
}
internal void InvokeOnDeserializing(object o, StreamingContext context)
{
foreach (MethodInfo mi in OnDeserializingMethods)
{
mi.Invoke(o, new object[] {context});
}
}
internal void InvokeOnDeserialized(object o, StreamingContext context)
{
foreach (MethodInfo mi in OnDeserializedMethods)
{
mi.Invoke(o, new object[] {context});
}
}
internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext)
{
foreach (MethodInfo mi in OnErrorMethods)
{
mi.Invoke(o, new object[] {context, errorContext});
}
}
internal JsonContract(Type underlyingType)
{
ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType");
@@ -286,11 +255,61 @@ namespace Newtonsoft.Json.Serialization
InternalReadType = ReadType.Read;
}
OnErrorMethods = new List<MethodInfo>();
OnSerializedMethods = new List<MethodInfo>();
OnSerializingMethods = new List<MethodInfo>();
OnDeserializedMethods = new List<MethodInfo>();
OnDeserializingMethods = new List<MethodInfo>();
OnErrorCallbacks = new List<SerializationErrorCallback>();
OnSerializedCallbacks = new List<SerializationCallback>();
OnSerializingCallbacks = new List<SerializationCallback>();
OnDeserializedCallbacks = new List<SerializationCallback>();
OnDeserializingCallbacks = new List<SerializationCallback>();
}
internal void InvokeOnSerializing(object o, StreamingContext context)
{
foreach (SerializationCallback callback in OnSerializingCallbacks)
{
callback(o, context);
}
}
internal void InvokeOnSerialized(object o, StreamingContext context)
{
foreach (SerializationCallback callback in OnSerializedCallbacks)
{
callback(o, context);
}
}
internal void InvokeOnDeserializing(object o, StreamingContext context)
{
foreach (SerializationCallback callback in OnDeserializingCallbacks)
{
callback(o, context);
}
}
internal void InvokeOnDeserialized(object o, StreamingContext context)
{
foreach (SerializationCallback callback in OnDeserializedCallbacks)
{
callback(o, context);
}
}
internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext)
{
foreach (SerializationErrorCallback callback in OnErrorCallbacks)
{
callback(o, context, errorContext);
}
}
internal static SerializationCallback CreateSerializationCallback(MethodInfo callbackMethodInfo)
{
return (o, context) => callbackMethodInfo.Invoke(o, new object[] { context });
}
internal static SerializationErrorCallback CreateSerializationErrorCallback(MethodInfo callbackMethodInfo)
{
return (o, context, econtext) => callbackMethodInfo.Invoke(o, new object[] { context, econtext });
}
}
}
@@ -168,6 +168,6 @@ namespace Newtonsoft.Json.Serialization
}
#endif
public bool IsReadOnlyDictionary { get; set; }
internal bool IsReadOnlyDictionary { get; set; }
}
}
@@ -578,10 +578,10 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
if (id != null && isTemporaryListReference)
throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.OnSerializingMethods.Count > 0 && isTemporaryListReference)
if (contract.OnSerializingCallbacks.Count > 0 && isTemporaryListReference)
throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.OnErrorMethods.Count > 0 && isTemporaryListReference)
if (contract.OnErrorCallbacks.Count > 0 && isTemporaryListReference)
throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (!arrayContract.IsMultidimensionalArray)
@@ -78,6 +78,15 @@ namespace Newtonsoft.Json.Utilities
}
#endif
public static MethodInfo Method(this Delegate d)
{
#if NETFX_CORE
return d.GetMethodInfo();
#else
return d.Method;
#endif
}
public static MemberTypes MemberType(this MemberInfo memberInfo)
{
#if !(NETFX_CORE || PORTABLE)