-Fixed IsoDateTimeConverter on DateTime properties with DateTimeFormatHandling.DateTimeOffset
-Fixed preserving object references with read only properties
This commit is contained in:
@@ -332,7 +332,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
{
|
||||
Error = (s, a) => a.ErrorContext.Handled = true
|
||||
});
|
||||
|
||||
|
||||
Assert.AreEqual(0, l.ChildId);
|
||||
}
|
||||
#endif
|
||||
@@ -394,7 +394,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
public class ChildClassVirtual : BaseClassVirtual
|
||||
{
|
||||
public virtual new bool IsTransient { get; set; }
|
||||
public new virtual bool IsTransient { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -413,7 +413,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
public class ResponseWithNewGenericPropertyVirtual<T> : SimpleResponse
|
||||
{
|
||||
public virtual new T Data { get; set; }
|
||||
public new virtual T Data { get; set; }
|
||||
}
|
||||
|
||||
public class ResponseWithNewGenericPropertyOverride<T> : ResponseWithNewGenericPropertyVirtual<T>
|
||||
@@ -1000,7 +1000,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
JObject oo = new JObject
|
||||
{
|
||||
{"title", v}
|
||||
{ "title", v }
|
||||
};
|
||||
|
||||
string output = o.ToString();
|
||||
@@ -1711,6 +1711,7 @@ keyword such as type of business.""
|
||||
{
|
||||
ExceptionAssert.Throws<JsonSerializationException>(() => { JsonConvert.SerializeObject(new BadJsonPropertyClass()); }, @"A member with the name 'pie' already exists on 'Newtonsoft.Json.Tests.TestObjects.BadJsonPropertyClass'. Use the JsonPropertyAttribute to specify another name.");
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
[Test]
|
||||
public void Unicode()
|
||||
@@ -3280,7 +3281,8 @@ Path '', line 1, position 1.");
|
||||
|
||||
ExceptionAssert.Throws<InvalidCastException>(
|
||||
() => { JsonConvert.DeserializeObject<JObject>(json); },
|
||||
new [] {
|
||||
new[]
|
||||
{
|
||||
"Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'Newtonsoft.Json.Linq.JObject'.",
|
||||
"Cannot cast from source type to destination type." // mono
|
||||
});
|
||||
@@ -3315,8 +3317,8 @@ Path '', line 1, position 1.");
|
||||
catch (JsonSerializationException ex)
|
||||
{
|
||||
Assert.IsTrue(ex.Message.StartsWith(@"Cannot deserialize the current JSON object (e.g. {""name"":""value""}) into type 'System.Collections.Generic.List`1[Newtonsoft.Json.Tests.TestObjects.Person]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly." + Environment.NewLine +
|
||||
@"To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object." + Environment.NewLine +
|
||||
@"Path ''"));
|
||||
@"To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object." + Environment.NewLine +
|
||||
@"Path ''"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3877,6 +3879,100 @@ Path '', line 1, position 1.");
|
||||
}", json);
|
||||
}
|
||||
|
||||
public class DateTimeOffsetWrapper
|
||||
{
|
||||
public DateTimeOffset DateTimeOffsetValue { get; set; }
|
||||
|
||||
public DateTime DateTimeValue { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDateTimeOffsetAndDateTime()
|
||||
{
|
||||
string jsonIsoText =
|
||||
@"{""DateTimeOffsetValue"":""2012-02-25T19:55:50.6095676+00:00"", ""DateTimeValue"":""2012-02-25T19:55:50.6095676+00:00""}";
|
||||
|
||||
DateTimeOffsetWrapper cISO = JsonConvert.DeserializeObject<DateTimeOffsetWrapper>(jsonIsoText, new JsonSerializerSettings
|
||||
{
|
||||
DateParseHandling = DateParseHandling.DateTimeOffset,
|
||||
Converters =
|
||||
{
|
||||
new IsoDateTimeConverter()
|
||||
}
|
||||
});
|
||||
DateTimeOffsetWrapper c = JsonConvert.DeserializeObject<DateTimeOffsetWrapper>(jsonIsoText, new JsonSerializerSettings
|
||||
{
|
||||
DateParseHandling = DateParseHandling.DateTimeOffset
|
||||
});
|
||||
|
||||
Assert.AreEqual(c.DateTimeOffsetValue, cISO.DateTimeOffsetValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CircularConstructorDeserialize()
|
||||
{
|
||||
CircularConstructor1 c1 = new CircularConstructor1(null)
|
||||
{
|
||||
StringProperty = "Value!"
|
||||
};
|
||||
|
||||
CircularConstructor2 c2 = new CircularConstructor2(null)
|
||||
{
|
||||
IntProperty = 1
|
||||
};
|
||||
|
||||
c1.C2 = c2;
|
||||
c2.C1 = c1;
|
||||
|
||||
string json = JsonConvert.SerializeObject(c1, new JsonSerializerSettings
|
||||
{
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
Formatting = Formatting.Indented
|
||||
});
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""C2"": {
|
||||
""IntProperty"": 1
|
||||
},
|
||||
""StringProperty"": ""Value!""
|
||||
}", json);
|
||||
|
||||
CircularConstructor1 newC1 = JsonConvert.DeserializeObject<CircularConstructor1>(@"{
|
||||
""C2"": {
|
||||
""IntProperty"": 1,
|
||||
""C1"": {}
|
||||
},
|
||||
""StringProperty"": ""Value!""
|
||||
}");
|
||||
|
||||
Assert.AreEqual("Value!", newC1.StringProperty);
|
||||
Assert.AreEqual(1, newC1.C2.IntProperty);
|
||||
Assert.AreEqual(null, newC1.C2.C1.StringProperty);
|
||||
Assert.AreEqual(null, newC1.C2.C1.C2);
|
||||
}
|
||||
|
||||
public class CircularConstructor1
|
||||
{
|
||||
public CircularConstructor2 C2 { get; internal set; }
|
||||
public string StringProperty { get; set; }
|
||||
|
||||
public CircularConstructor1(CircularConstructor2 c2)
|
||||
{
|
||||
C2 = c2;
|
||||
}
|
||||
}
|
||||
|
||||
public class CircularConstructor2
|
||||
{
|
||||
public CircularConstructor1 C1 { get; internal set; }
|
||||
public int IntProperty { get; set; }
|
||||
|
||||
public CircularConstructor2(CircularConstructor1 c1)
|
||||
{
|
||||
C1 = c1;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestClass
|
||||
{
|
||||
public string Key { get; set; }
|
||||
|
||||
@@ -47,6 +47,95 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
[TestFixture]
|
||||
public class PreserveReferencesHandlingTests : TestFixtureBase
|
||||
{
|
||||
public class Parent
|
||||
{
|
||||
public Child ReadOnlyChild
|
||||
{
|
||||
get { return Child1; }
|
||||
}
|
||||
|
||||
public Child Child1 { get; set; }
|
||||
public Child Child2 { get; set; }
|
||||
|
||||
public IList<string> ReadOnlyList
|
||||
{
|
||||
get { return List1; }
|
||||
}
|
||||
|
||||
public IList<string> List1 { get; set; }
|
||||
public IList<string> List2 { get; set; }
|
||||
}
|
||||
|
||||
public class Child
|
||||
{
|
||||
public string PropertyName { get; set; }
|
||||
}
|
||||
|
||||
public void SerializeReadOnlyProperty()
|
||||
{
|
||||
Child c = new Child
|
||||
{
|
||||
PropertyName = "value?"
|
||||
};
|
||||
IList<string> l = new List<string>
|
||||
{
|
||||
"value!"
|
||||
};
|
||||
Parent p = new Parent
|
||||
{
|
||||
Child1 = c,
|
||||
Child2 = c,
|
||||
List1 = l,
|
||||
List2 = l
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(p, new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
PreserveReferencesHandling = PreserveReferencesHandling.All
|
||||
});
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""$id"": ""1"",
|
||||
""ReadOnlyChild"": {
|
||||
""PropertyName"": ""value?""
|
||||
},
|
||||
""Child1"": {
|
||||
""$id"": ""2"",
|
||||
""PropertyName"": ""value?""
|
||||
},
|
||||
""Child2"": {
|
||||
""$ref"": ""2""
|
||||
},
|
||||
""ReadOnlyList"": [
|
||||
""value!""
|
||||
],
|
||||
""List1"": {
|
||||
""$id"": ""3"",
|
||||
""$values"": [
|
||||
""value!""
|
||||
]
|
||||
},
|
||||
""List2"": {
|
||||
""$ref"": ""3""
|
||||
}
|
||||
}", json);
|
||||
|
||||
Parent newP = JsonConvert.DeserializeObject<Parent>(json, new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
PreserveReferencesHandling = PreserveReferencesHandling.All
|
||||
});
|
||||
|
||||
Assert.AreEqual("value?", newP.Child1.PropertyName);
|
||||
Assert.AreEqual(newP.Child1, newP.Child2);
|
||||
Assert.AreEqual(newP.Child1, newP.ReadOnlyChild);
|
||||
|
||||
Assert.AreEqual("value!", newP.List1[0]);
|
||||
Assert.AreEqual(newP.List1, newP.List2);
|
||||
Assert.AreEqual(newP.List1, newP.ReadOnlyList);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeDictionarysWithPreserveObjectReferences()
|
||||
{
|
||||
|
||||
@@ -138,10 +138,10 @@ namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
#if !NET20
|
||||
if (t == typeof(DateTimeOffset))
|
||||
return reader.Value is DateTimeOffset ? reader.Value : new DateTimeOffset((DateTime)reader.Value);
|
||||
return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value);
|
||||
#endif
|
||||
|
||||
return reader.Value;
|
||||
return (reader.Value is DateTime) ? reader.Value : ((DateTimeOffset)reader.Value).DateTime;
|
||||
}
|
||||
|
||||
if (reader.TokenType != JsonToken.String)
|
||||
|
||||
@@ -497,7 +497,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
writer.WriteStartObject();
|
||||
|
||||
bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects);
|
||||
if (isReference)
|
||||
// don't make readonly fields the referenced value because they can't be deserialized to
|
||||
if (isReference && (member == null || member.Writable))
|
||||
{
|
||||
WriteReferenceIdProperty(writer, contract.UnderlyingType, value);
|
||||
}
|
||||
@@ -701,6 +702,9 @@ namespace Newtonsoft.Json.Serialization
|
||||
private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
|
||||
{
|
||||
bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
|
||||
// don't make readonly fields the referenced value because they can't be deserialized to
|
||||
isReference = (isReference && (member == null || member.Writable));
|
||||
|
||||
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
|
||||
bool writeMetadataObject = isReference || includeTypeDetails;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user