-Added support for type name handling with ISerializable content

This commit is contained in:
James Newton-King
2013-06-05 22:23:52 +12:00
parent 440cd42ade
commit c4e812b47a
5 changed files with 173 additions and 11 deletions
@@ -1539,6 +1539,159 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual(someValue, deserializedObject[contextKey]);
}
[Test]
public void TypeNameHandlingWithISerializableValues()
{
MyParent p = new MyParent
{
Child = new MyChild
{
MyProperty = "string!"
}
};
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
MissingMemberHandling = MissingMemberHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(p, settings);
Assert.AreEqual(@"{
""c"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.MyChild, Newtonsoft.Json.Tests"",
""p"": ""string!""
}
}", json);
MyParent p2 = JsonConvert.DeserializeObject<MyParent>(json, settings);
CustomAssert.IsInstanceOfType(typeof(MyChild), p2.Child);
Assert.AreEqual("string!", ((MyChild)p2.Child).MyProperty);
}
[Test]
public void TypeNameHandlingWithISerializableValuesAndArray()
{
MyParent p = new MyParent
{
Child = new MyChildList
{
"string!"
}
};
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
MissingMemberHandling = MissingMemberHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(p, settings);
Assert.AreEqual(@"{
""c"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.MyChildList, Newtonsoft.Json.Tests"",
""$values"": [
""string!""
]
}
}", json);
MyParent p2 = JsonConvert.DeserializeObject<MyParent>(json, settings);
CustomAssert.IsInstanceOfType(typeof(MyChildList), p2.Child);
Assert.AreEqual(1, ((MyChildList)p2.Child).Count);
Assert.AreEqual("string!", ((MyChildList)p2.Child)[0]);
}
[Test]
public void ParentTypeNameHandlingWithISerializableValues()
{
ParentParent pp = new ParentParent();
pp.ParentProp = new MyParent
{
Child = new MyChild
{
MyProperty = "string!"
}
};
JsonSerializerSettings settings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
MissingMemberHandling = MissingMemberHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(pp, settings);
Assert.AreEqual(@"{
""ParentProp"": {
""c"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.MyChild, Newtonsoft.Json.Tests"",
""p"": ""string!""
}
}
}", json);
ParentParent pp2 = JsonConvert.DeserializeObject<ParentParent>(json, settings);
MyParent p2 = pp2.ParentProp;
CustomAssert.IsInstanceOfType(typeof(MyChild), p2.Child);
Assert.AreEqual("string!", ((MyChild)p2.Child).MyProperty);
}
}
public class ParentParent
{
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
public MyParent ParentProp { get; set; }
}
[Serializable]
public class MyParent : ISerializable
{
public ISomeBase Child { get; internal set; }
public MyParent(SerializationInfo info, StreamingContext context)
{
Child = (ISomeBase)info.GetValue("c", typeof(ISomeBase));
}
public MyParent()
{
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("c", Child);
}
}
[DataContract]
public class MyChild : ISomeBase
{
[DataMember(Name = "p")]
public String MyProperty { get; internal set; }
}
public class MyChildList : List<string>, ISomeBase
{
}
public interface ISomeBase
{
}
public class Message
@@ -450,7 +450,7 @@ namespace Newtonsoft.Json.Serialization
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE40 || PORTABLE)
case JsonContractType.Serializable:
JsonISerializableContract serializableContract = (JsonISerializableContract) contract;
return CreateISerializable(reader, serializableContract, id);
return CreateISerializable(reader, serializableContract, member, id);
#endif
}
@@ -1264,7 +1264,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
}
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE40 || PORTABLE)
private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, string id)
private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty member, string id)
{
Type objectType = contract.UnderlyingType;
@@ -1290,7 +1290,16 @@ To fix this error either change the environment to be fully trusted, change the
if (!reader.Read())
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
serializationInfo.AddValue(memberName, JToken.ReadFrom(reader));
if (reader.TokenType == JsonToken.StartObject)
{
// this will read any potential type names embedded in json
object o = CreateObject(reader, null, null, null, contract, member, null);
serializationInfo.AddValue(memberName, o);
}
else
{
serializationInfo.AddValue(memberName, JToken.ReadFrom(reader));
}
break;
case JsonToken.Comment:
break;
@@ -818,9 +818,9 @@ To fix this error either change the environment to be fully trusted, change the
if (contract.UnderlyingType != member.PropertyContract.CreatedType)
return true;
}
else if (containerContract != null && containerContract.ItemContract != null)
else if (containerContract != null)
{
if (contract.UnderlyingType != containerContract.ItemContract.CreatedType)
if (containerContract.ItemContract == null || contract.UnderlyingType != containerContract.ItemContract.CreatedType)
return true;
}
else if (_rootContract != null && _serializeStack.Count == 1)