-Added DateParseHandling

This commit is contained in:
James Newton-King
2012-04-19 00:02:11 +12:00
parent 10256fcf68
commit 852a980659
13 changed files with 207 additions and 14 deletions
@@ -2399,6 +2399,77 @@ bye", reader.Value);
Assert.IsTrue(reader.Read());
}
[Test]
public void DateParseHandling()
{
string json = @"[""1970-01-01T00:00:00Z"",""\/Date(0)\/""]";
JsonTextReader reader = new JsonTextReader(new StringReader(json));
reader.DateParseHandling = Json.DateParseHandling.DateTime;
Assert.IsTrue(reader.Read());
Assert.IsTrue(reader.Read());
Assert.AreEqual(new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc), reader.Value);
Assert.AreEqual(typeof(DateTime), reader.ValueType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc), reader.Value);
Assert.AreEqual(typeof(DateTime), reader.ValueType);
Assert.IsTrue(reader.Read());
#if !NET20
reader = new JsonTextReader(new StringReader(json));
reader.DateParseHandling = Json.DateParseHandling.DateTimeOffset;
Assert.IsTrue(reader.Read());
Assert.IsTrue(reader.Read());
Assert.AreEqual(new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, TimeSpan.Zero), reader.Value);
Assert.AreEqual(typeof(DateTimeOffset), reader.ValueType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, TimeSpan.Zero), reader.Value);
Assert.AreEqual(typeof(DateTimeOffset), reader.ValueType);
Assert.IsTrue(reader.Read());
#endif
reader = new JsonTextReader(new StringReader(json));
reader.DateParseHandling = Json.DateParseHandling.None;
Assert.IsTrue(reader.Read());
Assert.IsTrue(reader.Read());
Assert.AreEqual(@"1970-01-01T00:00:00Z", reader.Value);
Assert.AreEqual(typeof(string), reader.ValueType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(@"/Date(0)/", reader.Value);
Assert.AreEqual(typeof(string), reader.ValueType);
Assert.IsTrue(reader.Read());
#if !NET20
reader = new JsonTextReader(new StringReader(json));
reader.DateParseHandling = Json.DateParseHandling.DateTime;
Assert.IsTrue(reader.Read());
reader.ReadAsDateTimeOffset();
Assert.AreEqual(new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, TimeSpan.Zero), reader.Value);
Assert.AreEqual(typeof(DateTimeOffset), reader.ValueType);
reader.ReadAsDateTimeOffset();
Assert.AreEqual(new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, TimeSpan.Zero), reader.Value);
Assert.AreEqual(typeof(DateTimeOffset), reader.ValueType);
Assert.IsTrue(reader.Read());
reader = new JsonTextReader(new StringReader(json));
reader.DateParseHandling = Json.DateParseHandling.DateTimeOffset;
Assert.IsTrue(reader.Read());
reader.ReadAsDateTime();
Assert.AreEqual(new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc), reader.Value);
Assert.AreEqual(typeof(DateTime), reader.ValueType);
reader.ReadAsDateTime();
Assert.AreEqual(new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc), reader.Value);
Assert.AreEqual(typeof(DateTime), reader.ValueType);
Assert.IsTrue(reader.Read());
#endif
}
}
public class SlowStream : Stream
@@ -80,6 +80,15 @@ namespace Newtonsoft.Json.Tests.Linq
v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"1.1")));
Assert.AreEqual(1.1, (double)v);
#if !NET20
v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"""1970-01-01T00:00:00+12:31"""))
{
DateParseHandling = DateParseHandling.DateTimeOffset
});
Assert.AreEqual(typeof(DateTimeOffset), v.Value.GetType());
Assert.AreEqual(new DateTimeOffset(JsonConvert.InitialJavaScriptDateTicks, new TimeSpan(12, 31, 0)), v.Value);
#endif
}
[Test]
@@ -920,6 +920,47 @@ keyword such as type of business.""
Assert.AreEqual(testDate, m2.MemberConverter);
}
[Test]
public void SerializerShouldUseMemberConverter_MsDate_DateParseNone()
{
DateTime testDate = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc);
MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate };
string json = JsonConvert.SerializeObject(m1, new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
});
Assert.AreEqual(@"{""DefaultConverter"":""\/Date(0)\/"",""MemberConverter"":""1970-01-01T00:00:00Z""}", json);
ExceptionAssert.Throws<JsonReaderException>(
"Could not convert string to DateTime: /Date(0)/. Line 1, position 33.",
() =>
{
JsonConvert.DeserializeObject<MemberConverterClass>(json, new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None
});
});
}
[Test]
public void SerializerShouldUseMemberConverter_IsoDate_DateParseNone()
{
DateTime testDate = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc);
MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate };
string json = JsonConvert.SerializeObject(m1, new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
});
Assert.AreEqual(@"{""DefaultConverter"":""1970-01-01T00:00:00Z"",""MemberConverter"":""1970-01-01T00:00:00Z""}", json);
MemberConverterClass m2 = JsonConvert.DeserializeObject<MemberConverterClass>(json);
Assert.AreEqual(testDate, m2.DefaultConverter);
Assert.AreEqual(testDate, m2.MemberConverter);
}
[Test]
public void SerializerShouldUseMemberConverterOverArgumentConverter()
{
+23
View File
@@ -0,0 +1,23 @@
namespace Newtonsoft.Json
{
/// <summary>
/// Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text.
/// </summary>
public enum DateParseHandling
{
/// <summary>
/// Date formatted strings are not parsed to a date type and are read as strings.
/// </summary>
None,
/// <summary>
/// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to <see cref="DateTime"/>.
/// </summary>
DateTime,
#if !NET20
/// <summary>
/// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to <see cref="DateTimeOffset"/>.
/// </summary>
DateTimeOffset
#endif
}
}
+11
View File
@@ -111,6 +111,7 @@ namespace Newtonsoft.Json
private DateTimeZoneHandling _dateTimeZoneHandling;
private int? _maxDepth;
private bool _hasExceededMaxDepth;
internal DateParseHandling _dateParseHandling;
/// <summary>
/// Gets the current reader state.
@@ -151,6 +152,15 @@ namespace Newtonsoft.Json
set { _dateTimeZoneHandling = value; }
}
/// <summary>
/// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
/// </summary>
public DateParseHandling DateParseHandling
{
get { return _dateParseHandling; }
set { _dateParseHandling = value; }
}
/// <summary>
/// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
/// </summary>
@@ -237,6 +247,7 @@ namespace Newtonsoft.Json
_currentState = State.Start;
_stack = new List<JsonPosition>(4);
_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
_dateParseHandling = DateParseHandling.DateTime;
CloseInput = true;
}
+21 -2
View File
@@ -60,6 +60,7 @@ namespace Newtonsoft.Json
private Formatting? _formatting;
private DateFormatHandling? _dateFormatHandling;
private DateTimeZoneHandling? _dateTimeZoneHandling;
private DateParseHandling? _dateParseHandling;
private CultureInfo _culture;
private int? _maxDepth;
private bool _maxDepthSet;
@@ -314,6 +315,15 @@ namespace Newtonsoft.Json
set { _dateTimeZoneHandling = value; }
}
/// <summary>
/// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
/// </summary>
public virtual DateParseHandling DateParseHandling
{
get { return _dateParseHandling ?? JsonSerializerSettings.DefaultDateParseHandling; }
set { _dateParseHandling = value; }
}
/// <summary>
/// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
@@ -383,11 +393,12 @@ namespace Newtonsoft.Json
jsonSerializer.ConstructorHandling = settings.ConstructorHandling;
jsonSerializer.Context = settings.Context;
// reader specific
// unset values won't override reader set values
// reader/writer specific
// unset values won't override reader/writer set values
jsonSerializer._formatting = settings._formatting;
jsonSerializer._dateFormatHandling = settings._dateFormatHandling;
jsonSerializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
jsonSerializer._dateParseHandling = settings._dateParseHandling;
jsonSerializer._culture = settings._culture;
jsonSerializer._maxDepth = settings._maxDepth;
jsonSerializer._maxDepthSet = settings._maxDepthSet;
@@ -498,6 +509,12 @@ namespace Newtonsoft.Json
previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value;
}
DateParseHandling? previousDateParseHandling = null;
if (_dateParseHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
{
previousDateParseHandling = reader.DateParseHandling;
reader.DateParseHandling = _dateParseHandling.Value;
}
int? previousMaxDepth = null;
if (_maxDepthSet && reader.MaxDepth != _maxDepth)
{
@@ -513,6 +530,8 @@ namespace Newtonsoft.Json
reader.Culture = previousCulture;
if (previousDateTimeZoneHandling != null)
reader.DateTimeZoneHandling = previousDateTimeZoneHandling.Value;
if (previousDateParseHandling != null)
reader.DateParseHandling = previousDateParseHandling.Value;
if (_maxDepthSet)
reader.MaxDepth = previousMaxDepth;
@@ -26,11 +26,13 @@ namespace Newtonsoft.Json
internal const Formatting DefaultFormatting = Formatting.None;
internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat;
internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime;
internal static readonly CultureInfo DefaultCulture;
internal Formatting? _formatting;
internal DateFormatHandling? _dateFormatHandling;
internal DateTimeZoneHandling? _dateTimeZoneHandling;
internal DateParseHandling? _dateParseHandling;
internal CultureInfo _culture;
internal int? _maxDepth;
internal bool _maxDepthSet;
@@ -169,6 +171,15 @@ namespace Newtonsoft.Json
set { _dateTimeZoneHandling = value; }
}
/// <summary>
/// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
/// </summary>
public DateParseHandling DateParseHandling
{
get { return _dateParseHandling ?? DefaultDateParseHandling; }
set { _dateParseHandling = value; }
}
/// <summary>
/// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
+15 -12
View File
@@ -137,20 +137,23 @@ namespace Newtonsoft.Json
{
string text = _stringReference.ToString();
if (text.Length > 0)
if (_dateParseHandling != DateParseHandling.None)
{
if (text[0] == '/')
if (text.Length > 0)
{
if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal))
if (text[0] == '/')
{
ParseDateMicrosoft(text);
return;
if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal))
{
ParseDateMicrosoft(text);
return;
}
}
else if (char.IsDigit(text[0]) && text.Length >= 19 && text.Length <= 40)
{
if (ParseDateIso(text))
return;
}
}
else if (char.IsDigit(text[0]) && text.Length >= 19 && text.Length <= 40)
{
if (ParseDateIso(text))
return;
}
}
@@ -164,7 +167,7 @@ namespace Newtonsoft.Json
const string isoDateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK";
#if !NET20
if (_readType == ReadType.ReadAsDateTimeOffset)
if (_readType == ReadType.ReadAsDateTimeOffset || (_readType == ReadType.Read && _dateParseHandling == DateParseHandling.DateTimeOffset))
{
DateTimeOffset dateTimeOffset;
if (DateTimeOffset.TryParseExact(text, isoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTimeOffset))
@@ -213,7 +216,7 @@ namespace Newtonsoft.Json
DateTime utcDateTime = JsonConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
#if !NET20
if (_readType == ReadType.ReadAsDateTimeOffset)
if (_readType == ReadType.ReadAsDateTimeOffset || (_readType == ReadType.Read && _dateParseHandling == DateParseHandling.DateTimeOffset))
{
SetToken(JsonToken.Date, new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset));
}
@@ -93,6 +93,7 @@
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="Converters\VersionConverter.cs" />
<Compile Include="DateFormatHandling.cs" />
<Compile Include="DateParseHandling.cs" />
<Compile Include="DateTimeZoneHandling.cs" />
<Compile Include="FormatterAssemblyStyle.cs" />
<Compile Include="Formatting.cs" />
@@ -105,6 +105,7 @@
<Compile Include="ConstructorHandling.cs" />
<Compile Include="Converters\VersionConverter.cs" />
<Compile Include="DateFormatHandling.cs" />
<Compile Include="DateParseHandling.cs" />
<Compile Include="DateTimeZoneHandling.cs" />
<Compile Include="FormatterAssemblyStyle.cs" />
<Compile Include="Formatting.cs" />
@@ -104,6 +104,7 @@
<Compile Include="Converters\VersionConverter.cs" />
<Compile Include="Converters\XmlNodeConverter.cs" />
<Compile Include="DateFormatHandling.cs" />
<Compile Include="DateParseHandling.cs" />
<Compile Include="DateTimeZoneHandling.cs" />
<Compile Include="FormatterAssemblyStyle.cs" />
<Compile Include="DefaultValueHandling.cs" />
@@ -77,6 +77,7 @@
<Compile Include="Converters\VersionConverter.cs" />
<Compile Include="Converters\XmlNodeConverter.cs" />
<Compile Include="DateFormatHandling.cs" />
<Compile Include="DateParseHandling.cs" />
<Compile Include="DateTimeZoneHandling.cs" />
<Compile Include="FormatterAssemblyStyle.cs" />
<Compile Include="DefaultValueHandling.cs" />
@@ -104,6 +104,7 @@
<Compile Include="ConstructorHandling.cs" />
<Compile Include="Converters\VersionConverter.cs" />
<Compile Include="DateFormatHandling.cs" />
<Compile Include="DateParseHandling.cs" />
<Compile Include="DateTimeZoneHandling.cs" />
<Compile Include="Formatting.cs" />
<Compile Include="JsonConstructorAttribute.cs" />