-Added Serializable attribute to exceptions

-Fixed deserializing null values into DataTables
-Fixed error when deserializing readonly IEnumerable<T> array properties
-Fixed not including type name for byte[] values
This commit is contained in:
JamesNK
2011-05-07 02:16:26 +00:00
parent 1197d35cbb
commit 6b2238c39c
14 changed files with 185 additions and 7 deletions
@@ -107,7 +107,7 @@ namespace Newtonsoft.Json.Tests.Converters
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DataTable d = (DataTable) value;
DataTable d = (DataTable)value;
writer.WriteValue(d.TableName);
}
@@ -121,7 +121,7 @@ namespace Newtonsoft.Json.Tests.Converters
public override bool CanConvert(Type objectType)
{
return (objectType == typeof (DataTable));
return (objectType == typeof(DataTable));
}
}
@@ -136,6 +136,55 @@ namespace Newtonsoft.Json.Tests.Converters
DataTable t2 = JsonConvert.DeserializeObject<DataTable>(json, new TestDataTableConverter());
Assert.AreEqual(t1.TableName, t2.TableName);
}
[Test]
public void SerializeDataTableWithNull()
{
var table = new DataTable();
table.Columns.Add("item");
table.Columns.Add("price", typeof(double));
table.Rows.Add("shirt", 49.99);
table.Rows.Add("pants", 54.99);
table.Rows.Add("shoes"); // no price
var json = JsonConvert.SerializeObject(table);
Assert.AreEqual(@"["
+ @"{""item"":""shirt"",""price"":49.99},"
+ @"{""item"":""pants"",""price"":54.99},"
+ @"{""item"":""shoes"",""price"":null}]", json);
}
[Test]
public void DerializeDataTableWithImplicitNull()
{
const string json = @"["
+ @"{""item"":""shirt"",""price"":49.99},"
+ @"{""item"":""pants"",""price"":54.99},"
+ @"{""item"":""shoes""}]";
var table = JsonConvert.DeserializeObject<DataTable>(json);
Assert.AreEqual("shirt", table.Rows[0]["item"]);
Assert.AreEqual("pants", table.Rows[1]["item"]);
Assert.AreEqual("shoes", table.Rows[2]["item"]);
Assert.AreEqual(49.99, (double)table.Rows[0]["price"], 0.01);
Assert.AreEqual(54.99, (double)table.Rows[1]["price"], 0.01);
Assert.IsInstanceOfType(typeof(System.DBNull), table.Rows[2]["price"]);
}
[Test]
public void DerializeDataTableWithExplicitNull()
{
const string json = @"["
+ @"{""item"":""shirt"",""price"":49.99},"
+ @"{""item"":""pants"",""price"":54.99},"
+ @"{""item"":""shoes"",""price"":null}]";
var table = JsonConvert.DeserializeObject<DataTable>(json);
Assert.AreEqual("shirt", table.Rows[0]["item"]);
Assert.AreEqual("pants", table.Rows[1]["item"]);
Assert.AreEqual("shoes", table.Rows[2]["item"]);
Assert.AreEqual(49.99, (double)table.Rows[0]["price"], 0.01);
Assert.AreEqual(54.99, (double)table.Rows[1]["price"], 0.01);
Assert.IsInstanceOfType(typeof(System.DBNull), table.Rows[2]["price"]);
}
}
}
#endif
@@ -41,5 +41,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.2.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.0.2.13702")]
[assembly: AssemblyFileVersion("4.0.2.13707")]
#endif
@@ -4310,5 +4310,24 @@ keyword such as type of business.""
var withParameterisedConstructor = JsonConvert.DeserializeObject<DTOWithParameterisedConstructor>(json);
Assert.AreEqual(withoutParameterisedConstructor.B, withParameterisedConstructor.B);
}
public class EnumerableArrayPropertyClass
{
public IEnumerable<int> Numbers
{
get
{
return new[] { 1, 2, 3 }; //fails
//return new List<int>(new[] { 1, 2, 3 }); //works
}
}
}
[Test]
public void SkipPopulatingArrayPropertyClass()
{
string json = JsonConvert.SerializeObject(new EnumerableArrayPropertyClass());
JsonConvert.DeserializeObject<EnumerableArrayPropertyClass>(json);
}
}
}
@@ -703,6 +703,56 @@ namespace Newtonsoft.Json.Tests.Serialization
}
}
public class Car
{
// included in JSON
public string Model { get; set; }
public DateTime Year { get; set; }
public List<string> Features { get; set; }
public object[] Objects { get; set; }
// ignored
[JsonIgnore]
public DateTime LastModified { get; set; }
}
[Test]
public void ByteArrays()
{
Car testerObject = new Car();
byte[] data = new byte[] {75, 65, 82, 73, 82, 65};
testerObject.Objects = new object[] { data, "prueba" };
JsonSerializerSettings jsonSettings = new JsonSerializerSettings();
jsonSettings.NullValueHandling = NullValueHandling.Ignore;
jsonSettings.TypeNameHandling = TypeNameHandling.All;
string output = JsonConvert.SerializeObject(testerObject, Formatting.Indented, jsonSettings);
string carClassRef = ReflectionUtils.GetTypeName(typeof(Car), FormatterAssemblyStyle.Simple);
Assert.AreEqual(output, @"{
""$type"": """ + carClassRef + @""",
""Year"": ""\/Date(-62135596800000+1300)\/"",
""Objects"": {
""$type"": ""System.Object[], mscorlib"",
""$values"": [
{
""$type"": ""System.Byte[], mscorlib"",
""$value"": ""S0FSSVJB""
},
""prueba""
]
}
}");
Car obj = JsonConvert.DeserializeObject<Car>(output, jsonSettings);
Assert.IsNotNull(obj);
Assert.IsTrue(obj.Objects[0] is byte[]);
Assert.AreEqual(data, obj.Objects[0]);
}
}
public class Message
@@ -101,7 +101,7 @@ namespace Newtonsoft.Json.Converters
dt.Columns.Add(new DataColumn(columnName, columnType));
}
dr[columnName] = reader.Value;
dr[columnName] = reader.Value ?? DBNull.Value;
reader.Read();
}
@@ -30,6 +30,9 @@ namespace Newtonsoft.Json
/// <summary>
/// The exception thrown when an error occurs while reading Json text.
/// </summary>
#if (!SILVERLIGHT && !WINDOWS_PHONE)
[Serializable]
#endif
public class JsonReaderException : Exception
{
/// <summary>
@@ -32,6 +32,9 @@ namespace Newtonsoft.Json
/// <summary>
/// The exception thrown when an error occurs during Json serialization or deserialization.
/// </summary>
#if (!SILVERLIGHT && !WINDOWS_PHONE)
[Serializable]
#endif
public class JsonSerializationException : Exception
{
/// <summary>
@@ -32,6 +32,9 @@ namespace Newtonsoft.Json
/// <summary>
/// The exception thrown when an error occurs while reading Json text.
/// </summary>
#if (!SILVERLIGHT && !WINDOWS_PHONE)
[Serializable]
#endif
public class JsonWriterException : Exception
{
/// <summary>
@@ -110,7 +110,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.2.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.0.2.13702")]
[assembly: AssemblyFileVersion("4.0.2.13707")]
#endif
[assembly: CLSCompliant(true)]
@@ -30,6 +30,9 @@ namespace Newtonsoft.Json.Schema
/// <summary>
/// Returns detailed information about the schema exception.
/// </summary>
#if (!SILVERLIGHT && !WINDOWS_PHONE)
[Serializable]
#endif
public class JsonSchemaException : Exception
{
/// <summary>
@@ -399,6 +399,20 @@ namespace Newtonsoft.Json.Serialization
return PopulateObject(existingValue, reader, objectContract, id);
}
JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract;
if (primitiveContract != null)
{
// if the content is inside $value then read past it
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
{
CheckedRead(reader);
object value = CreateValueInternal(reader, objectType, primitiveContract, member, existingValue);
CheckedRead(reader);
return value;
}
}
#if !SILVERLIGHT && !PocketPC
JsonISerializableContract serializableContract = contract as JsonISerializableContract;
if (serializableContract != null)
@@ -688,6 +702,13 @@ namespace Newtonsoft.Json.Serialization
{
object list = wrappedList.UnderlyingCollection;
// can't populate an existing array
if (wrappedList.IsFixedSize)
{
reader.Skip();
return wrappedList.UnderlyingCollection;
}
if (reference != null)
Serializer.ReferenceResolver.AddReference(this, reference, list);
@@ -86,6 +86,25 @@ namespace Newtonsoft.Json.Serialization
return Serializer.ContractResolver.ResolveContract(value.GetType());
}
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContract collectionValueContract)
{
if (contract.UnderlyingType == typeof (byte[]))
{
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract);
if (includeTypeDetails)
{
writer.WriteStartObject();
WriteTypeProperty(writer, contract.CreatedType);
writer.WritePropertyName(JsonTypeReflector.ValuePropertyName);
writer.WriteValue(value);
writer.WriteEndObject();
return;
}
}
writer.WriteValue(value);
}
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContract collectionValueContract)
{
JsonConverter converter = (member != null) ? member.Converter : null;
@@ -106,7 +125,7 @@ namespace Newtonsoft.Json.Serialization
}
else if (valueContract is JsonPrimitiveContract)
{
writer.WriteValue(value);
SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, collectionValueContract);
}
else if (valueContract is JsonStringContract)
{
@@ -46,6 +46,7 @@ namespace Newtonsoft.Json.Serialization
public const string IdPropertyName = "$id";
public const string RefPropertyName = "$ref";
public const string TypePropertyName = "$type";
public const string ValuePropertyName = "$value";
public const string ArrayValuesPropertyName = "$values";
public const string ShouldSerializePrefix = "ShouldSerialize";
@@ -194,7 +194,14 @@ namespace Newtonsoft.Json.Utilities
bool IList.IsFixedSize
{
get { return false; }
get
{
if (_genericCollection != null)
// ICollection<T> only has IsReadOnly
return _genericCollection.IsReadOnly;
else
return _list.IsFixedSize;
}
}
void IList.Remove(object value)