Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1249 lines (1067 sloc) 36.2 KB
#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 !PORTABLE
using global::System;
using global::System.Collections;
using global::System.Collections.Generic;
using global::System.Globalization;
using global::System.Runtime.Serialization.Formatters;
using global::Newtonsoft.Json.Linq;
using global::Newtonsoft.Json.Serialization;
using global::Newtonsoft.Json.Tests.TestObjects;
#if !NETFX_CORE
using global::NUnit.Framework;
#else
using global::Microsoft.VisualStudio.TestTools.UnitTesting;
using TestFixture = global::Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute;
using Test = global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
#endif
using global::Newtonsoft.Json.Utilities;
using global::System.Net;
using global::System.Runtime.Serialization;
using global::System.IO;
namespace Newtonsoft.Json.Tests.Serialization
{
[TestFixture]
public class TypeNameHandlingTests : TestFixtureBase
{
public class Wrapper
{
public IList<EmployeeReference> Array { get; set; }
public IDictionary<string, EmployeeReference> Dictionary { get; set; }
}
[Test]
public void SerializeWrapper()
{
Wrapper wrapper = new Wrapper();
wrapper.Array = new List<EmployeeReference>
{
new EmployeeReference()
};
wrapper.Dictionary = new Dictionary<string, EmployeeReference>
{
{ "First", new EmployeeReference() }
};
string json = JsonConvert.SerializeObject(wrapper, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
Assert.AreEqual(@"{
""Array"": [
{
""$id"": ""1"",
""Name"": null,
""Manager"": null
}
],
""Dictionary"": {
""First"": {
""$id"": ""2"",
""Name"": null,
""Manager"": null
}
}
}", json);
Wrapper w2 = JsonConvert.DeserializeObject<Wrapper>(json);
CustomAssert.IsInstanceOfType(typeof(List<EmployeeReference>), w2.Array);
CustomAssert.IsInstanceOfType(typeof(Dictionary<string, EmployeeReference>), w2.Dictionary);
}
[Test]
public void WriteTypeNameForObjects()
{
string employeeRef = ReflectionUtils.GetTypeName(typeof(EmployeeReference), FormatterAssemblyStyle.Simple);
EmployeeReference employee = new EmployeeReference();
string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
Assert.AreEqual(@"{
""$id"": ""1"",
""$type"": """ + employeeRef + @""",
""Name"": null,
""Manager"": null
}", json);
}
[Test]
public void DeserializeTypeName()
{
string employeeRef = ReflectionUtils.GetTypeName(typeof(EmployeeReference), FormatterAssemblyStyle.Simple);
string json = @"{
""$id"": ""1"",
""$type"": """ + employeeRef + @""",
""Name"": ""Name!"",
""Manager"": null
}";
object employee = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
CustomAssert.IsInstanceOfType(typeof(EmployeeReference), employee);
Assert.AreEqual("Name!", ((EmployeeReference)employee).Name);
}
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
[Test]
public void DeserializeTypeNameFromGacAssembly()
{
string cookieRef = ReflectionUtils.GetTypeName(typeof(Cookie), FormatterAssemblyStyle.Simple);
string json = @"{
""$id"": ""1"",
""$type"": """ + cookieRef + @"""
}";
object cookie = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
CustomAssert.IsInstanceOfType(typeof(Cookie), cookie);
}
#endif
[Test]
public void SerializeGenericObjectListWithTypeName()
{
string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
string personRef = typeof(Person).AssemblyQualifiedName;
List<object> values = new List<object>
{
new EmployeeReference
{
Name = "Bob",
Manager = new EmployeeReference {Name = "Frank"}
},
new Person
{
Department = "Department",
BirthDate = new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc),
LastModified = new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc)
},
"String!",
int.MinValue
};
string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
});
Assert.AreEqual(@"[
{
""$id"": ""1"",
""$type"": """ + employeeRef + @""",
""Name"": ""Bob"",
""Manager"": {
""$id"": ""2"",
""$type"": """ + employeeRef + @""",
""Name"": ""Frank"",
""Manager"": null
}
},
{
""$type"": """ + personRef + @""",
""Name"": null,
""BirthDate"": ""2000-12-30T00:00:00Z"",
""LastModified"": ""2000-12-30T00:00:00Z""
},
""String!"",
-2147483648
]", json);
}
[Test]
public void DeserializeGenericObjectListWithTypeName()
{
string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
string personRef = typeof(Person).AssemblyQualifiedName;
string json = @"[
{
""$id"": ""1"",
""$type"": """ + employeeRef + @""",
""Name"": ""Bob"",
""Manager"": {
""$id"": ""2"",
""$type"": """ + employeeRef + @""",
""Name"": ""Frank"",
""Manager"": null
}
},
{
""$type"": """ + personRef + @""",
""Name"": null,
""BirthDate"": ""\/Date(978134400000)\/"",
""LastModified"": ""\/Date(978134400000)\/""
},
""String!"",
-2147483648
]";
List<object> values = (List<object>)JsonConvert.DeserializeObject(json, typeof(List<object>), new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
});
Assert.AreEqual(4, values.Count);
EmployeeReference e = (EmployeeReference)values[0];
Person p = (Person)values[1];
Assert.AreEqual("Bob", e.Name);
Assert.AreEqual("Frank", e.Manager.Name);
Assert.AreEqual(null, p.Name);
Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.BirthDate);
Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.LastModified);
Assert.AreEqual("String!", values[2]);
Assert.AreEqual((long)int.MinValue, values[3]);
}
[Test]
public void DeserializeWithBadTypeName()
{
string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
string personRef = typeof(Person).AssemblyQualifiedName;
string json = @"{
""$id"": ""1"",
""$type"": """ + employeeRef + @""",
""Name"": ""Name!"",
""Manager"": null
}";
try
{
JsonConvert.DeserializeObject(json, typeof(Person), new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
});
}
catch (JsonSerializationException ex)
{
Assert.IsTrue(ex.Message.StartsWith(@"Type specified in JSON '" + employeeRef + @"' is not compatible with '" + personRef + @"'."));
}
}
[Test]
public void DeserializeTypeNameWithNoTypeNameHandling()
{
string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
string json = @"{
""$id"": ""1"",
""$type"": """ + employeeRef + @""",
""Name"": ""Name!"",
""Manager"": null
}";
JObject o = (JObject)JsonConvert.DeserializeObject(json);
Assert.AreEqual(@"{
""Name"": ""Name!"",
""Manager"": null
}", o.ToString());
}
[Test]
public void DeserializeTypeNameOnly()
{
string json = @"{
""$id"": ""1"",
""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee"",
""Name"": ""Name!"",
""Manager"": null
}";
ExceptionAssert.Throws<JsonSerializationException>(
"Type specified in JSON 'Newtonsoft.Json.Tests.TestObjects.Employee' was not resolved. Path '$type', line 3, position 56.",
() =>
{
JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
});
}
public interface ICorrelatedMessage
{
string CorrelationId { get; set; }
}
public class SendHttpRequest : ICorrelatedMessage
{
public SendHttpRequest()
{
RequestEncoding = "UTF-8";
Method = "GET";
}
public string Method { get; set; }
public Dictionary<string, string> Headers { get; set; }
public string Url { get; set; }
public Dictionary<string, string> RequestData;
public string RequestBodyText { get; set; }
public string User { get; set; }
public string Passwd { get; set; }
public string RequestEncoding { get; set; }
public string CorrelationId { get; set; }
}
[Test]
public void DeserializeGenericTypeName()
{
string typeName = typeof(SendHttpRequest).AssemblyQualifiedName;
string json = @"{
""$type"": """ + typeName + @""",
""RequestData"": {
""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"",
""Id"": ""siedemnaście"",
""X"": ""323""
},
""Method"": ""GET"",
""Url"": ""http://www.onet.pl"",
""RequestEncoding"": ""UTF-8"",
""CorrelationId"": ""xyz""
}";
ICorrelatedMessage message = JsonConvert.DeserializeObject<ICorrelatedMessage>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
});
CustomAssert.IsInstanceOfType(typeof(SendHttpRequest), message);
SendHttpRequest request = (SendHttpRequest)message;
Assert.AreEqual("xyz", request.CorrelationId);
Assert.AreEqual(2, request.RequestData.Count);
Assert.AreEqual("siedemnaście", request.RequestData["Id"]);
}
[Test]
public void SerializeObjectWithMultipleGenericLists()
{
string containerTypeName = typeof(Container).AssemblyQualifiedName;
string productListTypeName = typeof(List<Product>).AssemblyQualifiedName;
Container container = new Container
{
In = new List<Product>(),
Out = new List<Product>()
};
string json = JsonConvert.SerializeObject(container, Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
});
Assert.AreEqual(@"{
""$type"": """ + containerTypeName + @""",
""In"": {
""$type"": """ + productListTypeName + @""",
""$values"": []
},
""Out"": {
""$type"": """ + productListTypeName + @""",
""$values"": []
}
}", json);
}
public class TypeNameProperty
{
public string Name { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
public object Value { get; set; }
}
[Test]
public void WriteObjectTypeNameForProperty()
{
string typeNamePropertyRef = ReflectionUtils.GetTypeName(typeof(TypeNameProperty), FormatterAssemblyStyle.Simple);
TypeNameProperty typeNameProperty = new TypeNameProperty
{
Name = "Name!",
Value = new TypeNameProperty
{
Name = "Nested!"
}
};
string json = JsonConvert.SerializeObject(typeNameProperty, Formatting.Indented);
Assert.AreEqual(@"{
""Name"": ""Name!"",
""Value"": {
""$type"": """ + typeNamePropertyRef + @""",
""Name"": ""Nested!"",
""Value"": null
}
}", json);
TypeNameProperty deserialized = JsonConvert.DeserializeObject<TypeNameProperty>(json);
Assert.AreEqual("Name!", deserialized.Name);
CustomAssert.IsInstanceOfType(typeof(TypeNameProperty), deserialized.Value);
TypeNameProperty nested = (TypeNameProperty)deserialized.Value;
Assert.AreEqual("Nested!", nested.Name);
Assert.AreEqual(null, nested.Value);
}
[Test]
public void WriteListTypeNameForProperty()
{
string listRef = ReflectionUtils.GetTypeName(typeof(List<int>), FormatterAssemblyStyle.Simple);
TypeNameProperty typeNameProperty = new TypeNameProperty
{
Name = "Name!",
Value = new List<int> { 1, 2, 3, 4, 5 }
};
string json = JsonConvert.SerializeObject(typeNameProperty, Formatting.Indented);
Assert.AreEqual(@"{
""Name"": ""Name!"",
""Value"": {
""$type"": """ + listRef + @""",
""$values"": [
1,
2,
3,
4,
5
]
}
}", json);
TypeNameProperty deserialized = JsonConvert.DeserializeObject<TypeNameProperty>(json);
Assert.AreEqual("Name!", deserialized.Name);
CustomAssert.IsInstanceOfType(typeof(List<int>), deserialized.Value);
List<int> nested = (List<int>)deserialized.Value;
Assert.AreEqual(5, nested.Count);
Assert.AreEqual(1, nested[0]);
Assert.AreEqual(2, nested[1]);
Assert.AreEqual(3, nested[2]);
Assert.AreEqual(4, nested[3]);
Assert.AreEqual(5, nested[4]);
}
[Test]
public void DeserializeUsingCustomBinder()
{
string json = @"{
""$id"": ""1"",
""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee"",
""Name"": ""Name!""
}";
object p = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
Binder = new CustomSerializationBinder()
});
CustomAssert.IsInstanceOfType(typeof(Person), p);
Person person = (Person)p;
Assert.AreEqual("Name!", person.Name);
}
public class CustomSerializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
return typeof(Person);
}
}
#if !(NET20 || NET35)
[Test]
public void SerializeUsingCustomBinder()
{
TypeNameSerializationBinder binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests");
IList<object> values = new List<object>
{
new Customer
{
Name = "Caroline Customer"
},
new Purchase
{
ProductName = "Elbow Grease",
Price = 5.99m,
Quantity = 1
}
};
string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Binder = binder
});
//[
// {
// "$type": "Customer",
// "Name": "Caroline Customer"
// },
// {
// "$type": "Purchase",
// "ProductName": "Elbow Grease",
// "Price": 5.99,
// "Quantity": 1
// }
//]
Assert.AreEqual(@"[
{
""$type"": ""Customer"",
""Name"": ""Caroline Customer""
},
{
""$type"": ""Purchase"",
""ProductName"": ""Elbow Grease"",
""Price"": 5.99,
""Quantity"": 1
}
]", json);
IList<object> newValues = JsonConvert.DeserializeObject<IList<object>>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests")
});
CustomAssert.IsInstanceOfType(typeof(Customer), newValues[0]);
Customer customer = (Customer)newValues[0];
Assert.AreEqual("Caroline Customer", customer.Name);
CustomAssert.IsInstanceOfType(typeof(Purchase), newValues[1]);
Purchase purchase = (Purchase)newValues[1];
Assert.AreEqual("Elbow Grease", purchase.ProductName);
}
public class TypeNameSerializationBinder : SerializationBinder
{
public string TypeFormat { get; private set; }
public TypeNameSerializationBinder(string typeFormat)
{
TypeFormat = typeFormat;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.Name;
}
public override Type BindToType(string assemblyName, string typeName)
{
string resolvedTypeName = string.Format(TypeFormat, typeName);
return Type.GetType(resolvedTypeName, true);
}
}
#endif
[Test]
public void CollectionWithAbstractItems()
{
HolderClass testObject = new HolderClass();
testObject.TestMember = new ContentSubClass("First One");
testObject.AnotherTestMember = new Dictionary<int, IList<ContentBaseClass>>();
testObject.AnotherTestMember.Add(1, new List<ContentBaseClass>());
testObject.AnotherTestMember[1].Add(new ContentSubClass("Second One"));
testObject.AThirdTestMember = new ContentSubClass("Third One");
JsonSerializer serializingTester = new JsonSerializer();
serializingTester.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
StringWriter sw = new StringWriter();
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
serializingTester.TypeNameHandling = TypeNameHandling.Auto;
serializingTester.Serialize(jsonWriter, testObject);
}
string json = sw.ToString();
string contentSubClassRef = ReflectionUtils.GetTypeName(typeof(ContentSubClass), FormatterAssemblyStyle.Simple);
string dictionaryRef = ReflectionUtils.GetTypeName(typeof(Dictionary<int, IList<ContentBaseClass>>), FormatterAssemblyStyle.Simple);
string listRef = ReflectionUtils.GetTypeName(typeof(List<ContentBaseClass>), FormatterAssemblyStyle.Simple);
string expected = @"{
""TestMember"": {
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""First One""
},
""AnotherTestMember"": {
""$type"": """ + dictionaryRef + @""",
""1"": [
{
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""Second One""
}
]
},
""AThirdTestMember"": {
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""Third One""
}
}";
Assert.AreEqual(expected, json);
StringReader sr = new StringReader(json);
JsonSerializer deserializingTester = new JsonSerializer();
HolderClass anotherTestObject;
using (JsonTextReader jsonReader = new JsonTextReader(sr))
{
deserializingTester.TypeNameHandling = TypeNameHandling.Auto;
anotherTestObject = deserializingTester.Deserialize<HolderClass>(jsonReader);
}
Assert.IsNotNull(anotherTestObject);
CustomAssert.IsInstanceOfType(typeof(ContentSubClass), anotherTestObject.TestMember);
CustomAssert.IsInstanceOfType(typeof(Dictionary<int, IList<ContentBaseClass>>), anotherTestObject.AnotherTestMember);
Assert.AreEqual(1, anotherTestObject.AnotherTestMember.Count);
IList<ContentBaseClass> list = anotherTestObject.AnotherTestMember[1];
CustomAssert.IsInstanceOfType(typeof(List<ContentBaseClass>), list);
Assert.AreEqual(1, list.Count);
CustomAssert.IsInstanceOfType(typeof(ContentSubClass), list[0]);
}
[Test]
public void WriteObjectTypeNameForPropertyDemo()
{
Message message = new Message();
message.Address = "http://www.google.com";
message.Body = new SearchDetails
{
Query = "Json.NET",
Language = "en-us"
};
string json = JsonConvert.SerializeObject(message, Formatting.Indented);
// {
// "Address": "http://www.google.com",
// "Body": {
// "$type": "Newtonsoft.Json.Tests.Serialization.SearchDetails, Newtonsoft.Json.Tests",
// "Query": "Json.NET",
// "Language": "en-us"
// }
// }
Message deserialized = JsonConvert.DeserializeObject<Message>(json);
SearchDetails searchDetails = (SearchDetails)deserialized.Body;
// Json.NET
}
public class UrlStatus
{
public int Status { get; set; }
public string Url { get; set; }
}
[Test]
public void GenericDictionaryObject()
{
Dictionary<string, object> collection = new Dictionary<string, object>()
{
{"First", new UrlStatus{ Status = 404, Url = @"http://www.bing.com"}},
{"Second", new UrlStatus{Status = 400, Url = @"http://www.google.com"}},
{"List", new List<UrlStatus>
{
new UrlStatus {Status = 300, Url = @"http://www.yahoo.com"},
new UrlStatus {Status = 200, Url = @"http://www.askjeeves.com"}
}
}
};
string json = JsonConvert.SerializeObject(collection, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
string urlStatusTypeName = ReflectionUtils.GetTypeName(typeof(UrlStatus), FormatterAssemblyStyle.Simple);
Assert.AreEqual(@"{
""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"",
""First"": {
""$type"": """ + urlStatusTypeName + @""",
""Status"": 404,
""Url"": ""http://www.bing.com""
},
""Second"": {
""$type"": """ + urlStatusTypeName + @""",
""Status"": 400,
""Url"": ""http://www.google.com""
},
""List"": {
""$type"": ""System.Collections.Generic.List`1[[" + urlStatusTypeName + @"]], mscorlib"",
""$values"": [
{
""$type"": """ + urlStatusTypeName + @""",
""Status"": 300,
""Url"": ""http://www.yahoo.com""
},
{
""$type"": """ + urlStatusTypeName + @""",
""Status"": 200,
""Url"": ""http://www.askjeeves.com""
}
]
}
}", json);
object c = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
CustomAssert.IsInstanceOfType(typeof(Dictionary<string, object>), c);
Dictionary<string, object> newCollection = (Dictionary<string, object>)c;
Assert.AreEqual(3, newCollection.Count);
Assert.AreEqual(@"http://www.bing.com", ((UrlStatus)newCollection["First"]).Url);
List<UrlStatus> statues = (List<UrlStatus>)newCollection["List"];
Assert.AreEqual(2, statues.Count);
}
[Test]
public void SerializingIEnumerableOfTShouldRetainGenericTypeInfo()
{
string productClassRef = ReflectionUtils.GetTypeName(typeof(Product[]), FormatterAssemblyStyle.Simple);
CustomEnumerable<Product> products = new CustomEnumerable<Product>();
string json = JsonConvert.SerializeObject(products, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
Assert.AreEqual(@"{
""$type"": """ + productClassRef + @""",
""$values"": []
}", json);
}
public class CustomEnumerable<T> : IEnumerable<T>
{
//NOTE: a simple linked list
private readonly T value;
private readonly CustomEnumerable<T> next;
private readonly int count;
private CustomEnumerable(T value, CustomEnumerable<T> next)
{
this.value = value;
this.next = next;
count = this.next.count + 1;
}
public CustomEnumerable()
{
count = 0;
}
public CustomEnumerable<T> AddFirst(T newVal)
{
return new CustomEnumerable<T>(newVal, this);
}
public IEnumerator<T> GetEnumerator()
{
if (count == 0) // last node
yield break;
yield return value;
var nextInLine = next;
while (nextInLine != null)
{
if (nextInLine.count != 0)
yield return nextInLine.value;
nextInLine = nextInLine.next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
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();
testerObject.Year = new DateTime(2000, 10, 5, 1, 1, 1, DateTimeKind.Utc);
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"": ""2000-10-05T01:01:01Z"",
""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[]);
byte[] d = (byte[])obj.Objects[0];
CollectionAssert.AreEquivalent(data, d);
}
#if !(WINDOWS_PHONE || SILVERLIGHT || NETFX_CORE)
[Test]
public void ISerializableTypeNameHandlingTest()
{
//Create an instance of our example type
IExample e = new Example("Rob");
SerializableWrapper w = new SerializableWrapper
{
Content = e
};
//Test Binary Serialization Round Trip
//This will work find because the Binary Formatter serializes type names
//this.TestBinarySerializationRoundTrip(e);
//Test Json Serialization
//This fails because the JsonSerializer doesn't serialize type names correctly for ISerializable objects
//Type Names should be serialized for All, Auto and Object modes
this.TestJsonSerializationRoundTrip(w, TypeNameHandling.All);
this.TestJsonSerializationRoundTrip(w, TypeNameHandling.Auto);
this.TestJsonSerializationRoundTrip(w, TypeNameHandling.Objects);
}
private void TestJsonSerializationRoundTrip(SerializableWrapper e, TypeNameHandling flag)
{
Console.WriteLine("Type Name Handling: " + flag.ToString());
StringWriter writer = new StringWriter();
//Create our serializer and set Type Name Handling appropriately
JsonSerializer serializer = new JsonSerializer();
serializer.TypeNameHandling = flag;
//Do the actual serialization and dump to Console for inspection
serializer.Serialize(new JsonTextWriter(writer), e);
Console.WriteLine(writer.ToString());
Console.WriteLine();
//Now try to deserialize
//Json.Net will cause an error here as it will try and instantiate
//the interface directly because it failed to respect the
//TypeNameHandling property on serialization
SerializableWrapper f = serializer.Deserialize<SerializableWrapper>(new JsonTextReader(new StringReader(writer.ToString())));
//Check Round Trip
Assert.AreEqual(e, f, "Objects should be equal after round trip json serialization");
}
#endif
#if !(NET20 || NET35)
[Test]
public void SerializationBinderWithFullName()
{
Message message = new Message
{
Address = "jamesnk@testtown.com",
Body = new Version(1, 2, 3, 4)
};
string json = JsonConvert.SerializeObject(message, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full,
Binder = new MetroBinder(),
ContractResolver = new DefaultContractResolver
{
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
IgnoreSerializableAttribute = true
#endif
}
});
Assert.AreEqual(@"{
""$type"": "":::MESSAGE:::, AssemblyName"",
""Address"": ""jamesnk@testtown.com"",
""Body"": {
""$type"": "":::VERSION:::, AssemblyName"",
""Major"": 1,
""Minor"": 2,
""Build"": 3,
""Revision"": 4,
""MajorRevision"": 0,
""MinorRevision"": 4
}
}", json);
}
public class MetroBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
return null;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = "AssemblyName";
#if !NETFX_CORE
typeName = ":::" + serializedType.Name.ToUpper(CultureInfo.InvariantCulture) + ":::";
#else
typeName = ":::" + serializedType.Name.ToUpper() + ":::";
#endif
}
}
#endif
[Test]
public void TypeNameIntList()
{
TypeNameList<int> l = new TypeNameList<int>();
l.Add(1);
l.Add(2);
l.Add(3);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
1,
2,
3
]", json);
}
[Test]
public void TypeNameComponentList()
{
var c1 = new TestComponentSimple();
TypeNameList<object> l = new TypeNameList<object>();
l.Add(c1);
l.Add(new Employee
{
BirthDate = new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc),
Department = "Department!"
});
l.Add("String!");
l.Add(long.MaxValue);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
{
""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"",
""MyProperty"": 0
},
{
""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee, Newtonsoft.Json.Tests"",
""FirstName"": null,
""LastName"": null,
""BirthDate"": ""2000-12-12T12:12:12Z"",
""Department"": ""Department!"",
""JobTitle"": null
},
""String!"",
9223372036854775807
]", json);
TypeNameList<object> l2 = JsonConvert.DeserializeObject<TypeNameList<object>>(json);
Assert.AreEqual(4, l2.Count);
CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), l2[0]);
CustomAssert.IsInstanceOfType(typeof(Employee), l2[1]);
CustomAssert.IsInstanceOfType(typeof(string), l2[2]);
CustomAssert.IsInstanceOfType(typeof(long), l2[3]);
}
[Test]
public void TypeNameDictionary()
{
TypeNameDictionary<object> l = new TypeNameDictionary<object>();
l.Add("First", new TestComponentSimple { MyProperty = 1 });
l.Add("Second", "String!");
l.Add("Third", long.MaxValue);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"{
""First"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"",
""MyProperty"": 1
},
""Second"": ""String!"",
""Third"": 9223372036854775807
}", json);
TypeNameDictionary<object> l2 = JsonConvert.DeserializeObject<TypeNameDictionary<object>>(json);
Assert.AreEqual(3, l2.Count);
CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), l2["First"]);
Assert.AreEqual(1, ((TestComponentSimple)l2["First"]).MyProperty);
CustomAssert.IsInstanceOfType(typeof(string), l2["Second"]);
CustomAssert.IsInstanceOfType(typeof(long), l2["Third"]);
}
[Test]
public void TypeNameObjectItems()
{
TypeNameObject o1 = new TypeNameObject();
o1.Object1 = new TestComponentSimple { MyProperty = 1 };
o1.Object2 = 123;
o1.ObjectNotHandled = new TestComponentSimple { MyProperty = int.MaxValue };
o1.String = "String!";
o1.Integer = int.MaxValue;
string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
string expected = @"{
""Object1"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"",
""MyProperty"": 1
},
""Object2"": 123,
""ObjectNotHandled"": {
""MyProperty"": 2147483647
},
""String"": ""String!"",
""Integer"": 2147483647
}";
Assert.AreEqual(expected, json);
TypeNameObject o2 = JsonConvert.DeserializeObject<TypeNameObject>(json);
Assert.IsNotNull(o2);
CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), o2.Object1);
Assert.AreEqual(1, ((TestComponentSimple)o2.Object1).MyProperty);
CustomAssert.IsInstanceOfType(typeof(long), o2.Object2);
CustomAssert.IsInstanceOfType(typeof(JObject), o2.ObjectNotHandled);
Assert.AreEqual(@"{
""MyProperty"": 2147483647
}", o2.ObjectNotHandled.ToString());
}
}
public class Message
{
public string Address { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
public object Body { get; set; }
}
public class SearchDetails
{
public string Query { get; set; }
public string Language { get; set; }
}
public class Customer
{
public string Name { get; set; }
}
public class Purchase
{
public string ProductName { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
}
#if !(WINDOWS_PHONE || SILVERLIGHT || NETFX_CORE)
public class SerializableWrapper
{
public object Content { get; set; }
public override bool Equals(object obj)
{
SerializableWrapper w = obj as SerializableWrapper;
if (w == null)
return false;
return Equals(w.Content, Content);
}
}
public interface IExample
: ISerializable
{
String Name
{
get;
}
}
[Serializable]
public class Example
: IExample
{
public Example(String name)
{
this.Name = name;
}
protected Example(SerializationInfo info, StreamingContext context)
{
this.Name = info.GetString("name");
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("name", this.Name);
}
public String Name { get; set; }
public override bool Equals(object obj)
{
if (obj == null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj is IExample)
{
return this.Name.Equals(((IExample)obj).Name);
}
else
{
return false;
}
}
}
#endif
[JsonArray(ItemTypeNameHandling = TypeNameHandling.All)]
public class TypeNameList<T> : List<T>
{
}
[JsonDictionary(ItemTypeNameHandling = TypeNameHandling.All)]
public class TypeNameDictionary<T> : Dictionary<string, T>
{
}
[JsonObject(ItemTypeNameHandling = TypeNameHandling.All)]
public class TypeNameObject
{
public object Object1 { get; set; }
public object Object2 { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.None)]
public object ObjectNotHandled { get; set; }
public string String { get; set; }
public int Integer { get; set; }
}
}
#endif
Jump to Line
Something went wrong with that request. Please try again.